微信公众号开发---微信支付(JS API) JAVA

基于微信支付文档V3.3.7进行编码,使用JS API(网页内)并测试通过,应用在项目中。

Form:

[java]  view plain  copy
  1. public class PayForm extends BaseForm{  
  2.     private String code;              //通过code换取微信的openid,谁支付的  
  3.     private Integer transactionID;    //交易ID  
  4.     private String appId;             //公众账号ID  
  5.     private String timeStamp;         //时间戳  
  6.     private String nonceStr;          //随机字符串  
  7.     private String packages;          //订单详情扩展字符串  
  8.     private String paySign;           //签名  
  9.     private String openid;            //微信openid  
  10.     private Integer masterOrderID;    //订单ID  
  11.     //set get  
  12. }  

请求支付的Action:

[java]  view plain  copy
  1. @ParentPackage("main")  
  2. @Namespace("/pay")  
  3. @Controller  
  4. public class PayAction extends BaseAction{  
  5.      private PayForm form;  
  6.      @Resource  
  7.      private TransactionService transactionService;  
  8.      @Action(value = "weChatPay",  
  9.             results = {   
  10.             @Result(name = SUCCESS, location = "/html/transaction/jsp/weChatPay.jsp"),  
  11.             @Result(name =  ERROR , location = "/html/common/errors/sys_error.jsp")}  
  12.      )  
  13.      public String weChatPay(){  
  14.         SystemLogger.info("用户请求支付订单号:"+form.getTransactionID());  
  15.         if (StringUtils.isNotEmpty(form.getCode())) {  
  16.             String url =  WeixinUtil.getUrl().replace("CODE", form.getCode());  
  17.             String openid ="";  
  18.             try {  
  19.                 Map<String, Object> map = JsonUtil.getMapByUrl(url);   
  20.                 openid = map.get("openid").toString();  
  21.                 form.setOpenid(openid);  
  22.             } catch (Exception e) {  
  23.                 SystemLogger.info("用户请求支付订单号:"+form.getTransactionID()+"时拉取微信用户信息失败");  
  24.             }  
  25.             try {  
  26.                 transactionService.createWeChatRequest(form);  
  27.                 return SUCCESS;  
  28.             } catch (BusinessException e) {  
  29.                 SystemLogger.error(e.getMessage());  
  30.                 form.setMessage(e.getMessage());  
  31.                 return ERROR;  
  32.             }  
  33.         }else{  
  34.             SystemLogger.info("用户请求支付订单号:"+form.getTransactionID()+"的链接为非法链接,已拒绝");  
  35.             form.setMessage("请通过合法链接进行订单支付");  
  36.             return ERROR;  
  37.         }  
  38.      }  
  39.      @Override  
  40.      public Object getModel() {  
  41.       if(form==null){  
  42.           form = new PayForm();  
  43.       }  
  44.       return form;  
  45.      }  
  46. }  

微信支付结果回调请求的Action:

[java]  view plain  copy
  1. @ParentPackage("main")  
  2. @Namespace("/pay")  
  3. @Controller  
  4. public class NotifyAction {  
  5.         @Resource  
  6.     private TransactionService transactionService;  
  7.     @Action(value = "notify",  
  8.             results = {   
  9.             @Result(name = "success", type = "plainText",params = { "charSet""UTF-8"})},  
  10.             interceptorRefs = { @InterceptorRef("defaultStack")}  
  11.         )  
  12.      public String weChatNotify(){  
  13.         Map<String, String> requestMap = null;  
  14.         SortedMap<String, String> returnMap = new TreeMap<String, String>();  
  15.         String requestXML = "";  
  16.         try {  
  17.             requestMap = TenPayUtil.parseXml(ServletActionContext.getRequest());  
  18.             SystemLogger.info("接收到的微信支付回调通知:"+requestMap.toString());  
  19.             SortedMap<String, String> map = new TreeMap<String, String>();  
  20.             map.putAll(requestMap);  
  21.             String weixinSign = map.get("sign");  
  22.             map.remove("sign");  
  23.             String sign = TenPayUtil.sign(map, WeixinUtil.partnerKey);  
  24.             if(!sign.equals(weixinSign)){  
  25.                 SystemLogger.info("签名失败");  
  26.                 returnMap.put("return_code""FAIL");  
  27.                 returnMap.put("return_msg""签名失败");  
  28.                 requestXML = TenPayUtil.getRequestXml(returnMap);  
  29.             }else{  
  30.                 try {  
  31.                     //更新订单的状态等等操作...  
  32.                     returnMap.put("return_code""SUCCESS");  
  33.                     requestXML = TenPayUtil.getRequestXml(returnMap);  
  34.                 } catch (BusinessException e) {  
  35.                     SystemLogger.info(e.getMessage());  
  36.                     returnMap.put("return_code""FAIL");  
  37.                     returnMap.put("return_msg""签名失败");  
  38.                     requestXML = TenPayUtil.getRequestXml(returnMap);  
  39.                 }  
  40.             }  
  41.               
  42.         } catch (Exception e) {  
  43.             SystemLogger.info("转换微信请求参数错误");  
  44.             returnMap.put("return_code""FAIL");  
  45.             returnMap.put("return_msg""转换微信请求参数错误");  
  46.             requestXML = TenPayUtil.getRequestXml(returnMap);  
  47.         }  
  48.         try{   
  49.              PrintWriter out = ServletActionContext.getResponse().getWriter();     
  50.              out.print(requestXML);    
  51.              out.flush();    
  52.              out.close();    
  53.            }catch(Exception ex){    
  54.                  
  55.         }    
  56.         return "success";  
  57.      }  
  58. }  

Service:

[java]  view plain  copy
  1. @Transactional  
  2. @Service(value = "transactionService")  
  3. public class TransactionServiceImpl implements  TransactionService{  
  4. <span style="white-space:pre">    </span>.......  
  5.     @Override  
  6.     public void createWeChatRequest(PayForm form) throws BusinessException {  
  7.         Transaction po = this.getTransactionByID(form.getTransactionID());  
  8.         String shopOrderIDs = po.getMuiltFlag().equals("1") ? po.getRelateIDs() : po.getRelateID().toString();  
  9.         MasterOrder order = masterorderService.getMasterOrderByShopOrderIDs(shopOrderIDs);  
  10.         if(order.getPayFlag() == 1){  
  11.             throw new BusinessException("该笔订单已支付");  
  12.         }else{  
  13.             form.setMasterOrderID(order.getMasterOrderID());  
  14.             String payTypeID = po.getPayTypeID().toString();  
  15.             if(AppKeys.PAY_TYPE_ID_WECHAT.equals(payTypeID)){  
  16.                 //请求参数按参数名称大小进行排序  
  17.                 SortedMap<String, String> params = createSortedMap(form,po);  
  18.                 //签名  
  19.                 String sign = TenPayUtil.sign(params, WeixinUtil.partnerKey);  
  20.                 params.put("sign", sign);  
  21.                 //生成xml格式  
  22.                 String requestXML = TenPayUtil.getRequestXml(params);  
  23.                 //获取证书  
  24.                 HttpServletRequest request = ServletActionContext.getRequest();  
  25.                 InputStream instream = request.getSession().getServletContext().getResourceAsStream("/WEB-INF/weixinCert/apiclient_cert.p12");   
  26.                 String responseXML;  
  27.                 try {  
  28.                     //创建微信订单返回结果  
  29.                     responseXML = TenPayUtil.post(WeixinUtil.CREATE_ORDER_URL,WeixinUtil.partner,requestXML,instream);  
  30.                     Map<String,String> resultMap = XmlUtil.parseXml(responseXML);  
  31.                     String return_code = resultMap.get("return_code").toString();  
  32.                     if(return_code.equals("SUCCESS")){  
  33.                         //创建微信订单成功,获取微信预支付订单ID  
  34.                         String prepay_id = (String) resultMap.get("prepay_id");  
  35.                         SortedMap<String, String> finalpackage = new TreeMap<String, String>();  
  36.                         String prepay_id2 = "prepay_id="+prepay_id;  
  37.                         String packages = prepay_id2;  
  38.                         String timeStamp = TenPayUtil.getTimeStamp();  
  39.                         String nonceStr = TenPayUtil.createNonceStr();  
  40.                         finalpackage.put("appId", WeixinUtil.appId);    
  41.                         finalpackage.put("timeStamp", timeStamp);    
  42.                         finalpackage.put("nonceStr", nonceStr);    
  43.                         finalpackage.put("package", packages);    
  44.                         finalpackage.put("signType""MD5");  
  45.                         //签名  
  46.                         sign = TenPayUtil.sign(finalpackage, WeixinUtil.partnerKey);  
  47.                         form.setAppId(WeixinUtil.appId);  
  48.                         form.setTimeStamp(timeStamp);  
  49.                         form.setPaySign(sign);  
  50.                         form.setNonceStr(nonceStr);  
  51.                         form.setPackages(packages);  
  52.                     }else{  
  53.                         throw new BusinessException("统一支付接口获取预支付订单出错");  
  54.                     }  
  55.                 }catch (Exception e) {  
  56.                     e.printStackTrace();  
  57.                     SystemLogger.info(e.getMessage());  
  58.                     throw new BusinessException("支付异常");  
  59.                 }  
  60.             }else{  
  61.                 throw new BusinessException("手机端仅支持微信支付");  
  62.             }  
  63.         }  
  64.     }  
  65.       
  66.     private SortedMap<String, String> createSortedMap(PayForm form,Transaction po){  
  67.         //公众账号ID  
  68.         String appId = WeixinUtil.appId;  
  69.         //商户号  
  70.         String partner = WeixinUtil.partner;  
  71.         //当前时间  
  72.         String currTime = TenPayUtil.getCurrTime();  
  73.         //8位日期  
  74.         String strTime = currTime.substring(8, currTime.length());  
  75.         //四位随机数  
  76.         String strRandom = TenPayUtil.getRandomNum(4);  
  77.         //10位序列号,可以自行调整。  
  78.         String strReq = strTime + strRandom;  
  79.         //商户号  
  80.         String mch_id = partner;  
  81.         //子商户号  非必输  
  82.         String sub_mch_id="";  
  83.         //设备号   非必输  
  84.         String device_info="";  
  85.         //随机字符串   
  86.         String nonce_str = strReq;  
  87.         //商品描述  
  88.         String body = po.getTitle();  
  89.         //附加数据  
  90.         String attach = "测试";  
  91.         //商户订单号  
  92.         String out_trade_no = po.getTransactionID().toString();  
  93.         int intMoney = (int)(po.getAmount()*100);  
  94.         //总金额以分为单位,不带小数点  
  95.         int total_fee = intMoney;  
  96.         //订单生成的机器 IP  
  97.         String spbill_create_ip = ServletActionContext.getRequest().getRemoteAddr();  
  98.         //订 单 生 成 时 间   非必输  
  99.         String time_start = currTime;  
  100.         //订单失效时间      非必输  
  101.         String time_expire = "";  
  102.         //商品标记   非必输  
  103.         String goods_tag = "";  
  104.         //这里notify_url是 支付完成后微信发给该链接信息,可以判断会员是否支付成功,改变订单状态等。  
  105.         String notify_url =WeixinUtil.notifyURL;  
  106.         //交易类型  
  107.         String trade_type = "JSAPI";  
  108.         //用户标识  
  109.         String openid = form.getOpenid();  
  110.         //非必输  
  111.         String product_id = "";  
  112.         SortedMap<String, String> packageParams = new TreeMap<String, String>();  
  113.         packageParams.put("appid", appId);    
  114.         packageParams.put("mch_id", mch_id);    
  115.         packageParams.put("nonce_str", nonce_str);    
  116.         packageParams.put("body", body);    
  117.         packageParams.put("attach", attach);    
  118.         packageParams.put("out_trade_no", out_trade_no);    
  119.         packageParams.put("total_fee", total_fee+"");     
  120.         packageParams.put("spbill_create_ip", spbill_create_ip);    
  121.         packageParams.put("notify_url", notify_url);    
  122.         packageParams.put("trade_type", trade_type);    
  123.         packageParams.put("openid", openid);    
  124.           
  125.         return packageParams;  
  126.     }  
  127. <span style="white-space:pre">    </span>......  
  128. }  

TenPayUtil:

[java]  view plain  copy
  1. public class TenPayUtil {  
  2.     /** 
  3.      * 对请求参数名ASCII码从小到大排序后签名 
  4.      * @param openid 
  5.      * @param userId 
  6.      * @return 
  7.      */  
  8.     public static String sign(SortedMap<String, String> params,String KEY){  
  9.         Set<Entry<String,String>> entrys=params.entrySet();    
  10.         Iterator<Entry<String,String>> it=entrys.iterator();    
  11.         StringBuffer result = new StringBuffer();  
  12.         while(it.hasNext())    
  13.         {    
  14.            Entry<String,String> entry=it.next();    
  15.            result.append(entry.getKey())  
  16.                  .append("=")  
  17.                  .append(entry.getValue())  
  18.                  .append("&");  
  19.         }    
  20.         result.append("key=").append(KEY);  
  21.         SystemLogger.info(result.toString());  
  22.         String sign = "";  
  23.         try {  
  24.             sign = MD5Util.MD5(result.toString());  
  25.         } catch (Exception e) {  
  26.             e.printStackTrace();  
  27.         }  
  28.         return sign.toString().toUpperCase();  
  29.     }  
  30.       
  31.     public static String getRequestXml(SortedMap<String,String> params){  
  32.         StringBuffer sb = new StringBuffer();  
  33.         sb.append("<xml>");  
  34.         Set es = params.entrySet();  
  35.         Iterator it = es.iterator();  
  36.         while(it.hasNext()) {  
  37.             Map.Entry entry = (Map.Entry)it.next();  
  38.             String k = (String)entry.getKey();  
  39.             String v = (String)entry.getValue();  
  40.             if ("body".equalsIgnoreCase(k)||"attach".equalsIgnoreCase(k)||"goodstag".equalsIgnoreCase(k)||"sign".equalsIgnoreCase(k)) {  
  41.                 sb.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">");  
  42.             }else {  
  43.                 sb.append("<"+k+">"+v+"</"+k+">");  
  44.             }  
  45.         }  
  46.         sb.append("</xml>");  
  47.         return sb.toString();  
  48.     }  
  49.     /** 
  50.      * 生成随机字符串 
  51.      * @return 
  52.      */  
  53.     public static String createNonceStr() {  
  54.         return UUID.randomUUID().toString().toUpperCase().replace("-""");  
  55.     }  
  56.     /** 
  57.      * 获取当前日期 yyyyMMdd 
  58.      *  
  59.      * @param date 
  60.      * @return String 
  61.      */  
  62.     public static String getCurrTime() {  
  63.         SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");  
  64.         String strDate = formatter.format(new Date());  
  65.         return strDate;  
  66.     }  
  67.     /** 
  68.      * 生成特定位数的随机数字 
  69.      * @param length 
  70.      * @return 
  71.      */  
  72.     public static String getRandomNum(int length) {  
  73.         String val = "";  
  74.         Random random = new Random();  
  75.         for (int i = 0; i < length; i++) {  
  76.             val += String.valueOf(random.nextInt(10));  
  77.         }  
  78.         return val;  
  79.     }  
  80.     /** 
  81.      * 获取时间戳 
  82.      * @return 
  83.      */  
  84.     public static String getTimeStamp() {  
  85.         return String.valueOf(System.currentTimeMillis() / 1000);  
  86.     }  
  87.     /** 
  88.      *  
  89.      * @param url         请求URL 
  90.      * @param MCH_ID      商户号 
  91.      * @param requestXML  请求参数 
  92.      * @param instream    证书流 
  93.      * @return 
  94.      * @throws NoSuchAlgorithmException 
  95.      * @throws CertificateException 
  96.      * @throws IOException 
  97.      * @throws KeyManagementException 
  98.      * @throws UnrecoverableKeyException 
  99.      * @throws KeyStoreException 
  100.      */  
  101.     public static String post(String url,String MCH_ID,String requestXML,InputStream instream) throws NoSuchAlgorithmException, CertificateException, IOException, KeyManagementException, UnrecoverableKeyException, KeyStoreException{  
  102.         KeyStore keyStore  = KeyStore.getInstance("PKCS12");  
  103.         try {  
  104.             keyStore.load(instream, MCH_ID.toCharArray());  
  105.         }  finally {  
  106.             instream.close();  
  107.         }  
  108.         SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, MCH_ID.toCharArray()).build();  
  109.         SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(  
  110.                 sslcontext,  
  111.                 new String[] { "TLSv1" },  
  112.                 null,  
  113.                 SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);  
  114.         CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();  
  115.         String result = "";  
  116.         try {  
  117.             HttpPost httpPost = new HttpPost(url);  
  118.             StringEntity  reqEntity  = new StringEntity(requestXML,"UTF-8");  
  119.             reqEntity.setContentType("application/x-www-form-urlencoded");   
  120.             httpPost.setEntity(reqEntity);  
  121.             CloseableHttpResponse response = httpclient.execute(httpPost);  
  122.             try {  
  123.                 HttpEntity entity = response.getEntity();  
  124.                 if (entity != null) {  
  125.                     BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent(),"UTF-8"));  
  126.                     String text;  
  127.                     while ((text = bufferedReader.readLine()) != null) {  
  128.                         result +=text;  
  129.                     }  
  130.                 }  
  131.                 EntityUtils.consume(entity);  
  132.             } finally {  
  133.                 response.close();  
  134.             }  
  135.         } finally {  
  136.             httpclient.close();  
  137.         }  
  138.         return result;  
  139.     }  
  140.       
  141.     /**  
  142.      * 解析微信发来的请求(XML)  
  143.      *   
  144.      * @param request  
  145.      * @return  
  146.      * @throws Exception  
  147.      */    
  148.     @SuppressWarnings("unchecked")    
  149.     public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {    
  150.         // 将解析结果存储在HashMap中    
  151.         Map<String, String> map = new HashMap<String, String>();    
  152.         // 从request中取得输入流    
  153.         InputStream inputStream = request.getInputStream();    
  154.         // 读取输入流    
  155.         SAXReader reader = new SAXReader();    
  156.         Document document = reader.read(inputStream);    
  157.         // 得到xml根元素    
  158.         Element root = document.getRootElement();    
  159.         // 得到根元素的所有子节点    
  160.         List<Element> elementList = root.elements();    
  161.         // 遍历所有子节点    
  162.         for (Element e : elementList)    
  163.             map.put(e.getName(), e.getText());    
  164.         // 释放资源    
  165.         inputStream.close();    
  166.         inputStream = null;    
  167.         return map;    
  168.     }    
  169. }  

weChatPay.jsp

[html]  view plain  copy
  1. <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>  
  2. <%@ include file="/html/common/taglibs.jsp"%>  
  3. <!DOCTYPE html>  
  4. <html>    
  5. <head>  
  6. <meta charset="utf-8" >  
  7. <title>订单支付</title>  
  8. <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">  
  9. <meta name="apple-mobile-web-app-capable" content="yes">  
  10. <meta name="apple-mobile-web-app-status-bar-style" content="black">  
  11. <link rel="stylesheet" href="<s:url value='/html/css/common/common.css' />" >  
  12. <link rel="stylesheet" href="<s:url value='/html/css/index.css' />" >  
  13. </head>  
  14. <body>  
  15.       
  16. <div class="content">  
  17.     <a href="javascript:callpay();" class="payment">微信支付</a>  
  18.     <hr>  
  19.     <img src="<s:url value='/html/images/logo.svg' />" class="logo">  
  20. </div>  
  21.   
  22. <script type="text/javascript">  
  23. var clicked = !1;  // false  
  24.   
  25. function callpay() {  
  26.     if (clicked) return false;  
  27.     clicked = !0;      // true  
  28.   
  29.     WeixinJSBridge.invoke('getBrandWCPayRequest', {  
  30.         "appId" : "${appId}",  
  31.         "timeStamp" : "${timeStamp}",   
  32.         "nonceStr" : "${nonceStr}",   
  33.         "package" : "${packages}",  
  34.         "signType" : "MD5",   
  35.         "paySign" : "${paySign}"   
  36.     }, function(res) {  
  37.         WeixinJSBridge.log(res.err_msg);  
  38.         if (res.err_msg == "get_brand_wcpay_request:ok") {    
  39.             window.location.href = "../pay/payResult.action?transactionID=${transactionID}&masterOrderID=${masterOrderID}";  
  40.         } else if (res.err_msg == "get_brand_wcpay_request:cancel") {    
  41.             clicked = !1;  // false  
  42.             window.location.href = "../pay/payResult.action?message=crm.pay.cancel";  
  43.         } else {   
  44.             clicked = !1;  // false  
  45.             window.location.href = "../pay/payResult.action?message=crm.pay.error";  
  46.         }  
  47.     })  
  48. }  
  49. </script>  
  50. </body>  
  51. </html>  
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值