java对接微信支付

对接微信扫码支付(模式2),前端使用velocity技术

(1)调用微信支付接口(view层)  此部分业务逻辑部分可以省略

  1 @RequestMapping("/wxpay.htm")
  2     public ModelAndView wxpay(HttpServletRequest request,HttpServletResponse response, String id, String type,
  3             String payment_id)
  4     {
  5         ModelAndView mv = new JModelAndView("wxpay.html",
  6                 configService.getSysConfig(),
  7                 this.userConfigService.getUserConfig(), 1, request,
  8                 response);
  9     /*处理业务逻辑开始,如获取当前订单单号,充值单号,积分兑换单号,获取当前价格
 10             此处为自定义部分        
 11                 */
 12         OrderForm of = null;
 13         Predeposit obj = null;
 14         GoldRecord gold = null;
 15         IntegralGoodsOrder ig_order = null;
 16         String redirect =null;
 17         String msg ="返回订单列表";
 18         if (type.equals("goods") || type.equals("group")) {
 19             of = this.orderFormService.getObjById(CommUtil.null2Long(id));
 20         }
 21         if (type.equals("cash")) { 
 22             obj = this.predepositService.getObjById(CommUtil.null2Long(id));
 23         }
 24         if (type.equals("gold")) {
 25             gold = this.goldRecordService.getObjById(CommUtil.null2Long(id));
 26         }
 27         if (type.equals("integral")) {
 28             ig_order = this.integralGoodsOrderService.getObjById(CommUtil
 29                     .null2Long(id));
 30         }
 31         // 获取提交的商品价格
 32         String order_price = "";
 33         if (type.equals("goods") ) {
 34             double order_total_price = 0d;
 35             //order_price = CommUtil.null2String(of.getTotalPrice());
 36             if (of != null ) {            
 37                 if(of.getLiuCheng()==0){   ////普通实物订单 TotalPrice已经包含运费
 38                     order_total_price = CommUtil.null2Double(of
 39                             .getTotalPrice());
 40                     if (!CommUtil.null2String(of.getChild_order_detail())
 41                             .equals("")) {
 42                         List<Map> maps = this.orderFormTools
 43                                 .queryGoodsInfo(of.getChild_order_detail());
 44                         for (Map map : maps) {
 45                             OrderForm child_order = this.orderFormService
 46                                     .getObjById(CommUtil.null2Long(map
 47                                             .get("order_id")));
 48                             if(child_order.getOrder_status()==10){   //这里判断如果是主订单的话,就会和次订单一块结算,但是如果次订单结算了,就不在添加使用。
 49                                 order_total_price = order_total_price
 50                                         + CommUtil.null2Double(child_order
 51                                                 .getTotalPrice());
 52                             }
 53                         }
 54                     }
 55                     redirect = "/buyer/order.htm";
 56                 }else if(of.getLiuCheng()==1){ ///预售订单这里只支付定金
 57                     if(of.getOrder_status() == 10){
 58                         order_total_price = CommUtil.null2Double(of.getDingJin_price());
 59                         mv.addObject("level", "1");
 60                     }else if(of.getOrder_status() == 18){
 61                         order_total_price = CommUtil.add(CommUtil.null2Double(of.getWeiKuan_price()), of.getShip_price()); 
 62                         mv.addObject("level", "2");
 63                     }
 64                     redirect = "/buyer/yuShouOrder.htm";
 65                 }
 66             }
 67             
 68             order_price = CommUtil.null2String(order_total_price) ;
 69         }
 70         //微信扫码后暂不支持自动跳转,根据订单不同,在支付二维码下提示返回不同的列表
 71         if (type.equals("group")) {
 72             //Map queryGroupInfo = this.orderFormTools.queryGroupInfo(of.getGroup_info());
 73             redirect = "/buyer/group.htm";            
 74             order_price =  CommUtil.null2String(of.getTotalPrice()); 
 75         }
 76         if (type.equals("cash")) {
 77             redirect = "/buyer/predeposit_list.htm";
 78             msg = "返回充值列表";
 79             order_price = CommUtil.null2String(obj.getPd_amount());
 80         }
 81         if (type.equals("gold")) {
 82             redirect = "/seller/gold_record_list.htm";
 83             msg = "返回金币日志";
 84             order_price = CommUtil.null2String(gold.getGold_money());
 85         }
 86         if (type.equals("integral")) {
 87             redirect = "/buyer/integral_order_list.htm";
 88             order_price = CommUtil.null2String(ig_order.getIgo_trans_fee());
 89         }
 90         mv.addObject("redirect", redirect);
 91         mv.addObject("msg", msg);
 92         // 获取提交的商品名称
 93         String product_name = "";
 94         if (type.equals("goods") || type.equals("group")) {
 95             product_name = of.getOrder_id();
 96         }
 97         if (type.equals("cash")) {
 98             product_name = obj.getPd_sn();
 99         }
100         if (type.equals("gold")) {
101             product_name = gold.getGold_sn();
102         }
103         if (type.equals("integral")) {
104             product_name = ig_order.getIgo_order_sn();
105         }
106         //自定義的參數
107         String attach = "";
108         if (type.equals("goods") || type.equals("group")) {
109             attach = type + "," + of.getId().toString();
110         }
111         if (type.equals("cash")) {
112             attach = type + "," + obj.getId().toString();
113         }
114         if (type.equals("gold")) {
115             attach = type + "," + gold.getId().toString();
116         }
117         if (type.equals("integral")) {
118             attach = type + "," + ig_order.getId().toString();
119         }
120         String desc = "商品:" + product_name;
121         // 获取提交的订单号
122         String out_trade_no = "";
123         if (type.equals("goods") || type.equals("group")) {
124             out_trade_no = of.getOrder_id();
125         }
126         if (type.endsWith("cash")) {
127             out_trade_no = obj.getPd_sn();
128         }
129         if (type.endsWith("gold")) {
130             out_trade_no = gold.getGold_sn();
131         }
132         if (type.equals("integral")) {
133             out_trade_no = ig_order.getIgo_order_sn();
134         }
135 /*        OrderForm order = this.orderFormService.getObjById(CommUtil
136                 .null2Long(orderid));*/
137         
138         //double order_total_price = 0d;
139         
140             mv.addObject("order_total_price", order_price);
141     /*
142              处理业务逻辑结束 ----------
143     
144     
145     **/
146             //获取预支付信息
147             Map<String,Object> token = null;    
148             String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath();                                        
149             String notify= basePath + "/wxBuyerNotify.htm?attach="+attach;  //微信支付回调地址,付款成功后调用该地址
150             Money para = new Money();     //将订单编号和订单金额封装到实体中(Money)
151             para.setId(product_name);
152 //            para.setCash(new BigDecimal(order_total_price));
153             para.setCash(new BigDecimal(0.01));   //测试使用,不获取实际订单金额
154             mv.addObject("type", type);
155             mv.addObject("id", id);
156             try
157             {
158                 token = wxPayService.getPrepayKey(para,notify);    //调用微信API,生成页面二维码信息
159                 String barCode = (String)token.get("codeUrl");
160                 mv.addObject("barCode", barCode);
161             }
162             catch(Exception e)
163             {
164                 mv = new JModelAndView("error.html", configService.getSysConfig(),
165                         this.userConfigService.getUserConfig(), 1, request,
166                         response);
167                 mv.addObject("op_title", "参数错误,付款失败");
168                 mv.addObject("url", CommUtil.getURL(request) + "/index.htm");
169             }
170             
171         
172         return mv;
173     }

(2)view层用到的 实体,接口和工具类

  <1>实体类:Money

 1 public class Money implements Serializable {
 2     /**
 3      * 主键编号
 4      */
 5     private String id;
 6 
 7     /**
 8      * 用户编号
 9      */
10     private String userId;
11 
12     /**
13      * 支付金额
14      */
15     private BigDecimal cash;
16 
17     /**
18      * 手机号码
19      */
20     private String phone;
21     
22     /**
23      * 支付方式:1支付宝,2微信,3银联,4余额
24      */
25     private String type;

  <2>微信支付接口:IWxPayService

 1     public interface IWxPayService {
 2 
 3     /**
 4      * 获取微信支付链接
 5      * @param record
 6      * @param path
 7      * @param ds
 8      * @return
 9      * @throws Exception
10      */
11     Map<String,Object> getPrepayKey(Money record,String path)throws Exception;
12 
13     /**
14      * 微信支付成功回调
15      * @param request
16      * @return
17      */
18     int updateWxPay(HttpServletRequest request);
19 
20     /**
21      * 形成支付订单信息
22      * @param para
23      * @return
24      */
25     PayOrder insertOrder(Money para);
26 
27     /**
28      * 用户余额支付
29      * @param order
30      * @param user
31      * @return
32      */
33     int updateStorePay(PayOrder order, User user);
34 
35     /**
36      * 形成支付宝支付信息
37      * @param id
38      * @param string
39      * @param user_id
40      * @param basePath
41      * @return
42      */
43     String createAlipay(Long id, String cash, long user_id, String basePath);
44 
45     /**
46      * 支付宝支付回调
47      * @param orderid
48      * @param fee
49      * @param storeId
50      * @return
51      */
52     int updateAliPay(String orderid, String fee, String storeId);
53 
54     /**
55      * 形成银联支付信息
56      * @param para
57      * @return
58      */
59     String packPay(Money para,PayOrder order);
60 
61     /**
62      * 银联支付回调
63      * @param request
64      * @return
65      */
66     int unionNotfy(HttpServletRequest request);
67 }

  <3>实现类:WxPayServiceImpl

  1 @Service
  2 @Transactional
  3 public class WxPayServiceImpl implements IWxPayService 
  4     {
  5             /**
  6      * 获取packageValue
  7      * @param response
  8      * @param request
  9      * @param orderCode String 用户编号
 10      * @param ds boolean 是否打赏
 11      * @return
 12      */    
 13     @Override
 14     public Map<String,Object> getPrepayKey(Money record,String path)
 15             throws Exception
 16             {
 17                 Pay pay = new Pay();    //此处为微信支付返回的参数,封装为实体(Pay)                    
 18                 String orderCode = record.getId();
 19                 if(StringUtils.isBlank(orderCode))
 20                 {
 21                     return null;
 22                 }        
 23                 orderCode = orderCode.trim();
 24                                 
 25                 BigDecimal money = record.getCash();        
 26                 if(money == null)
 27                 {
 28                     return null;
 29                 }                    
 30                 packRecharge(orderCode,pay,money,path);
 31                 packSign(pay);//形成签名
 32                 return packToMap(pay,true);
 33             }
 34             private void packRecharge(String ucode,Pay pay,BigDecimal money,String notify)
 35                 {
 36                     
 37                     float cash = money.floatValue();
 38                     int total = (int)(cash * 100);
 39                     String orderCode = ucode.trim();        
 40                     String prekey = doInBackground(orderCode.trim(),total,pay,notify);
 41                     pay.setPrepayid(prekey);
 42                 }
 43                     /**
 44              * 形成调起支付的签名
 45              * @param pay Pay
 46              */
 47             private void packSign(Pay pay)
 48             {
 49                 //将数据封装到map中
 50                 if(pay == null)
 51                 {
 52                     return;
 53                 }
 54                 Map<String,Object> map = packToMap(pay,false);
 55                 if(map != null)
 56                 {
 57                     String sign = WXPayDataUtils.genPackageSign(map);
 58                     pay.setSign(sign);
 59                 }        
 60             }
 61             /**
 62              * 请求微信后台获取预支付单号
 63              * @param ucode String
 64              * @param total int
 65              * @return
 66              */
 67             private  String  doInBackground(String ucode,int total,Pay pay,String notify) {
 68 
 69                 String entity = WXPayDataUtils.genProductArgs(ucode,total,pay,notify);
 70                 Map<String,String> map =WXPayDataUtils.sendPost(WXPayDataUtils.WX_VERIFY_URL, entity);
 71                 pay.setCodeUrl(map.get("code_url"));
 72                 String id = map.get("prepay_id");
 73                 return id;
 74             }
 75 
 76             private Map<String,Object> packToMap(Pay pay,boolean flag)
 77             {
 78                 if(pay == null)
 79                 {
 80                     return null;
 81                 }
 82                 Map<String,Object> param = new HashMap<String,Object>();
 83                 if(pay.getAppid() != null)
 84                 {
 85                     param.put("appid", pay.getAppid().trim());
 86                 }
 87                 if(pay.getPartnerid() != null)
 88                 {
 89                     param.put("partnerid", pay.getPartnerid().trim());
 90                 }
 91                 if(pay.getPrepayid() != null)
 92                 {
 93                     param.put("prepayid", pay.getPrepayid().trim());
 94                 }
 95                 if(pay.getPack() != null)
 96                 {
 97                     param.put("package", pay.getPack().trim());
 98                 }
 99                 if(pay.getNoncestr() != null)
100                 {
101                     param.put("noncestr", pay.getNoncestr().trim());
102                 }
103                 if(pay.getTimestamp() != null)
104                 {
105                     param.put("timestamp", pay.getTimestamp().trim());
106                 }
107                 if(pay.getSign() != null && flag)
108                 {
109                     param.put("sign", pay.getSign());
110                 }
111                 if(pay.getAppkey() != null && flag)
112                 {
113                     param.put("appkey", pay.getAppkey());
114                 }
115                 if(pay.getCodeUrl() !=null && flag)
116                 {
117                     param.put("codeUrl",pay.getCodeUrl());
118                 }
119                 return param;
120             }
121                     }

  <4>实体:Pay

public class Pay {

            private String appid;
            private String appkey;
            private String noncestr;
            private String pack;
            private String partnerid;
            private String prepayid;
            private String timestamp;
            private String sign;
            private String codeUrl;
            .
            .
            .
            }

  <5>微信支付工具类:WXPayDataUtils

  1 package com.sanmi.wx.util;
  2 
  3 import java.io.ByteArrayInputStream;
  4 import java.io.IOException;
  5 import java.io.InputStream;
  6 import java.util.Calendar;
  7 import java.util.HashMap;
  8 import java.util.Iterator;
  9 import java.util.List;
 10 import java.util.Map;
 11 import java.util.Random;
 12 import java.util.Set;
 13 import java.util.SortedMap;
 14 import java.util.TreeMap;
 15 import java.util.TreeSet;
 16 
 17 import org.apache.commons.lang3.StringUtils;
 18 import org.apache.commons.logging.Log;
 19 import org.apache.commons.logging.LogFactory;
 20 import org.apache.http.HttpResponse;
 21 import org.apache.http.client.methods.HttpPost;
 22 import org.apache.http.client.params.ClientPNames;
 23 import org.apache.http.entity.StringEntity;
 24 import org.apache.http.impl.client.DefaultHttpClient;
 25 import org.apache.http.util.EntityUtils;
 26 import org.jdom.Document;
 27 import org.jdom.Element;
 28 import org.jdom.JDOMException;
 29 import org.jdom.input.SAXBuilder;
 30 
 31 import com.sanmi.wx.client.HttpClientConnectionManager;
 32 import com.sdsanmi.core.domain.Pay;
 33 
 34 
 35 /**
 36  * 微信支付数据
 37  * @author Admin
 38  *
 39  */
 40 public class WXPayDataUtils {
 41     private static final Log logger = LogFactory.getLog(WXPayDataUtils.class);
 42     
 43     public static final String APPID = "***********";//微信分配的公众账号ID
 44     public static final String MCH_ID = "********";//微信支付分配的商户号
 45     public static final String API_KEY="as4d4s41a4s4789a5w4********";//商户号对应的密钥
 46     public static final String APP_SECRET = "c1634fe990550b96********";//应用对应的凭证
 47     public static final String BODY = "东地美商城";//商品或支付单简要描述
 48     public static final String NOTIFY_URL = "http://121.40.35.3/test";//接收微信支付异步通知回调地址
 49     public static final String TRADE_TYPE = "NATIVE";//交易类型
 50     public static final String WX_VERIFY_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";//微信统一下单请求url                                                
 51     public static final String WX_CLOSE_ORDER = "https://api.mch.weixin.qq.com/pay/closeorder";//关闭订单接口
 52     public static final String WX_ORDER_QUERY = "https://api.mch.weixin.qq.com/pay/orderquery";//查询订单接口
 53     
 54     public static DefaultHttpClient httpclient;
 55 
 56       static
 57       {
 58         httpclient = new DefaultHttpClient();
 59         httpclient = (DefaultHttpClient)HttpClientConnectionManager.getSSLInstance(httpclient);
 60       }
 61     
 62      /**
 63      *  拼接要传递的参数
 64      * @param order
 65      * @return
 66      */
 67     public static String genProductArgs(String order,int cash,Pay pay,String notify) {
 68 
 69         SortedMap<String, Object> map = new TreeMap<String, Object>();
 70         String appid = APPID;//微信分配的公众账号ID
 71         String mch_id= MCH_ID;//微信支付分配的商户号
 72         String nonce_str = getRandomString(18);//随机字符串
 73         String body = BODY;        
 74         
 75         String out_trade_no = order;//商户订单号
 76         String total_fee = String.valueOf(cash);//订单总金额,单位为分
 77         String spbill_create_ip = "127.0.0.1";//APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IP,暂时为本机地址
 78         String notify_url = notify;//接收微信支付异步通知回调地址,不支持参数
 79         String trade_type = TRADE_TYPE;//交易类型
 80         
 81         map.put("appid", appid);
 82         map.put("mch_id", mch_id);
 83         map.put("nonce_str", nonce_str);
 84         map.put("body", body);
 85         map.put("out_trade_no", out_trade_no);
 86         map.put("total_fee", total_fee);
 87         map.put("spbill_create_ip", spbill_create_ip);
 88         map.put("notify_url", notify_url);
 89         map.put("trade_type", trade_type);
 90 
 91         String sign = genPackageSign(map);
 92         map.put("sign", sign);//签名
 93         pay.setSign(sign);
 94         pay.setAppid(appid);
 95         pay.setAppkey(API_KEY);
 96         pay.setPartnerid(mch_id);
 97         pay.setPack("Sign=WXPay");
 98         pay.setNoncestr(nonce_str);
 99         pay.setTimestamp(String.valueOf(System.currentTimeMillis() / 1000));
100         String xmlstring = "<xml>" + "<appid>" + appid + "</appid>"
101                  + "<mch_id>" + mch_id + "</mch_id>"
102                  + "<nonce_str>" + nonce_str + "</nonce_str>"
103                  + "<sign>" + sign + "</sign>"
104                  + "<body><![CDATA[" + body + "]]></body>" 
105                  + "<out_trade_no>" + out_trade_no + "</out_trade_no>"
106                  + "<total_fee>" + total_fee + "</total_fee>"
107                  + "<spbill_create_ip>" + spbill_create_ip + "</spbill_create_ip>"
108                  + "<notify_url>" + notify_url + "</notify_url>"
109                  + "<trade_type>" + trade_type + "</trade_type>"
110                  + "</xml>";
111         return xmlstring;
112 
113     }
114       
115     /**
116      * 生成签名
117      * @param params
118      * @return
119      */
120     public static String genPackageSign(Map<String,Object> params) {
121         StringBuilder sb = new StringBuilder();
122         
123         TreeSet<String> sort = new TreeSet<String>(params.keySet());        
124         for (String key : sort) {
125            String value = (String) params.get(key);
126            sb.append(key);
127             sb.append("=");
128             sb.append(value);
129             sb.append("&");
130        }
131         sb.append("key=");
132         sb.append(API_KEY);//API密钥
133         String packageSign = MD5.MD5Encode((sb.toString()));
134         packageSign = packageSign.toUpperCase();
135         return packageSign;
136     }
137     /**
138      * 生成随机字符串
139      * @param length
140      * @return
141      */
142     public static String getRandomString(int length) { //length表示生成字符串的长度
143         String base = "abcdefghijklmnopqrstuvwxyz0123456789";   
144         Random random = new Random();   
145         StringBuffer sb = new StringBuffer();   
146         for (int i = 0; i < length; i++) {   
147             int number = random.nextInt(base.length());   
148             sb.append(base.charAt(number));   
149         }   
150         return sb.toString();   
151      }  
152     /**
153      * 实现Java访问url
154      * @param url param
155      * @return
156      * @throws JDOMException
157      * @throws IOException
158      */
159      public static Map<String,String> sendPost(String url, String param) {  
160           DefaultHttpClient client = new DefaultHttpClient();
161           client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);          
162           HttpPost httpost= HttpClientConnectionManager.getPostMethod(url);                    
163           Map<String,String> map = null;
164          try {
165              httpost.setEntity(new StringEntity(param, "UTF-8"));
166              HttpResponse response = httpclient.execute(httpost);
167              String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");    
168             // System.out.println("=====" + jsonStr);
169             if(jsonStr.indexOf("FAIL")!=-1){
170                 return map;
171             }
172              map = doXMLParse(jsonStr);
173             //prepay_id  = (String) map.get("prepay_id");
174         } catch (Exception e) {
175             logger.error("request weixin prepay_id error!", e);
176             e.printStackTrace();
177         }
178         return map;
179         }  
180      /**
181       * 关闭订单支付
182       * @param url
183       * @param param
184       * @return
185       */
186      public static boolean sendClosePost(String url,String param)
187      {
188          boolean flag = true;
189           DefaultHttpClient client = new DefaultHttpClient();
190           client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
191           HttpPost httpost= HttpClientConnectionManager.getPostMethod(url);
192           try
193           {
194               httpost.setEntity(new StringEntity(param,"UTF-8"));
195               HttpResponse response = httpclient.execute(httpost);
196               String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");              
197               if(jsonStr.indexOf("FAIL")!=-1){
198                     return false;
199                 }
200                
201           }
202           catch(Exception e)
203           {
204               flag = false;
205           }
206           return flag;
207      }
208      
209      /**
210       * 形成支付网址
211       * @param phone
212       * @return
213       */
214      public static String createPayUrl(String order)
215      {
216          if(StringUtils.isBlank(order))
217          {
218              return null;
219          }
220          StringBuffer sb = new StringBuffer();
221         //weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX
222          Map<String,Object> param = new HashMap<String,Object>();
223          param.put("appid",APPID);
224          param.put("mch_id", MCH_ID);
225          param.put("time_stamp", String.valueOf(Calendar.getInstance().getTimeInMillis()));
226          param.put("nonce_str", getNewId());
227          param.put("product_id", order);
228          String sign = genPackageSign(param);
229          param.put("sign",sign);
230          sb.append("weixin://wxpay/bizpayurl?");
231          sb.append(genUrlParam(param));
232          return sb.toString();
233      }
234      
235      /**
236       * 形成随机字符串
237       * @return
238       */
239      private static String getNewId()
240      {
241          return java.util.UUID.randomUUID().toString().toLowerCase().replaceAll("-","");
242      }
243      
244      private static String genUrlParam(Map<String,Object> param)
245      {
246          StringBuffer sb = new StringBuffer();         
247          TreeSet<String> sort = new TreeSet<String>(param.keySet());
248          for (String key : sort) {
249                String value = (String) param.get(key);
250                sb.append(key);
251                 sb.append("=");
252                 sb.append(value);
253                 sb.append("&");
254            }
255          String params = sb.toString();
256          while(params.endsWith("&"))
257          {
258              params = params.substring(0,params.length() - 1);
259          }
260          return params;
261      }
262      /**
263       * 查询订单是否存在
264       * @param url
265       * @param param
266       * @return
267       */
268      public static boolean sendQueryPost(String url,String param)
269      {
270          boolean flag = true;
271           DefaultHttpClient client = new DefaultHttpClient();
272           client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
273           HttpPost httpost= HttpClientConnectionManager.getPostMethod(url);
274           try
275           {
276               httpost.setEntity(new StringEntity(param,"UTF-8"));
277               HttpResponse response = httpclient.execute(httpost);
278               String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");        
279               System.out.println(jsonStr);
280               if(jsonStr.indexOf("FAIL")!=-1){
281                     return false;
282                 }
283                
284           }
285           catch(Exception e)
286           {
287               flag = false;
288           }
289           return flag;
290      }
291         /**
292          * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。
293          * @param strxml
294          * @return
295          * @throws JDOMException
296          * @throws IOException
297          */
298         public static Map<String, String> doXMLParse(String strxml) throws Exception {
299             if(null == strxml || "".equals(strxml)) {
300                 return null;
301             }
302             
303             Map<String, String> m = new HashMap<String, String>();
304             InputStream in = String2Inputstream(strxml);
305             SAXBuilder builder = new SAXBuilder();
306             Document doc = builder.build(in);
307             Element root = doc.getRootElement();
308             List<?> list = root.getChildren();
309             Iterator<?> it = list.iterator();
310             while(it.hasNext()) {
311                 Element e = (Element) it.next();
312                 String k = e.getName();
313                 String v = "";
314                 List<?> children = e.getChildren();
315                 if(children.isEmpty()) {
316                     v = e.getTextNormalize();
317                 } else {
318                     v = getChildrenText(children);
319                 }
320                 
321                 m.put(k, v);
322             }
323             
324             //关闭流
325             in.close();
326             
327             return m;
328         }
329         /**
330          * 获取子结点的xml
331          * @param children
332          * @return String
333          */
334         public static String getChildrenText(List<?> children) {
335             StringBuffer sb = new StringBuffer();
336             if(!children.isEmpty()) {
337                 Iterator<?> it = children.iterator();
338                 while(it.hasNext()) {
339                     Element e = (Element) it.next();
340                     String name = e.getName();
341                     String value = e.getTextNormalize();
342                     List<?> list = e.getChildren();
343                     sb.append("<" + name + ">");
344                     if(!list.isEmpty()) {
345                         sb.append(getChildrenText(list));
346                     }
347                     sb.append(value);
348                     sb.append("</" + name + ">");
349                 }
350             }
351             
352             return sb.toString();
353         }
354         public static InputStream String2Inputstream(String str) {
355             return new ByteArrayInputStream(str.getBytes());
356         }
357         
358         /**
359          * 支付成功微信回调
360          * @param children
361          * @return String
362          * @throws Exception 
363          */
364         public static Map<String,String> doReqToMap(InputStream inputStream) throws Exception {
365             // 解析结果存储在HashMap
366             Map<String, String> map = new HashMap<String, String>();
367             SAXBuilder builder = new SAXBuilder();
368             Document doc = builder.build(inputStream);
369             Element root = doc.getRootElement();
370             List<?> list = root.getChildren();
371             Iterator<?> it = list.iterator();
372             while(it.hasNext()) {
373                 Element e = (Element) it.next();
374                 String k = e.getName();
375                 String v = "";
376                 List<?> children = e.getChildren();
377                 if(children.isEmpty()) {
378                     v = e.getTextNormalize();
379                 } else {
380                     v = getChildrenText(children);
381                 }
382                 
383                 map.put(k, v);
384             }
385             
386             //关闭流
387             inputStream.close();
388          
389             return map;
390         }
391         
392         /**
393          * 处理返回数据
394          * @param children
395          * @return String
396          */
397         public static Map<String,Object> responseData(String prepayId) {
398             SortedMap<String, Object> map = new TreeMap<String, Object>();
399             map.put("appid", APPID);//微信分配的公众账号ID
400             map.put("partnerid", MCH_ID);//微信支付分配的商户号
401             map.put("prepayid", prepayId);//支付交易会话ID
402             map.put("package", "Sign=WXPay");//扩展字段 固定值Sign=WXPay
403             map.put("noncestr", getRandomString(18));//随机字符串
404             map.put("timestamp", String.valueOf(System.currentTimeMillis()/1000));//10位时间戳
405 
406             String sign = genPackageSign(map);
407             map.put("sign", sign);//签名
408             
409             return map;
410         }
411 
412         /**
413          * 关闭上次订单
414          * @param order
415          */
416         public static void closePrePay(String order) {
417             //查询订单是否存在
418             if(checkExists(order))
419             {
420                 String closeStr = closeParam(createCloseParam(order));            
421                 sendClosePost(WXPayDataUtils.WX_CLOSE_ORDER, closeStr);
422             }
423             
424         }
425             
426         /**
427          * 查询订单是否存在
428          * @param order
429          * @return boolean true存在;false不存在
430          */
431         private static boolean checkExists(String order)
432         {
433             boolean flag = false;
434             String closeStr = closeParam(createCloseParam(order));            
435             flag = sendQueryPost(WXPayDataUtils.WX_ORDER_QUERY, closeStr);
436             return flag;
437         }
438         /**
439          * 行程请求参数
440          * @param order
441          * @return
442          */
443         private static Map<String,Object> createCloseParam(String order)
444         {
445             SortedMap<String, Object> map = new TreeMap<String, Object>();
446             map.put("appid", APPID);//微信分配的公众账号ID
447             map.put("mch_id", MCH_ID);//微信支付分配的商户号
448             map.put("out_trade_no", order);//商家订单编号            
449             map.put("nonce_str", getRandomString(18));//随机字符串            
450             String sign = genPackageSign(map);
451             map.put("sign", sign);//签名
452             return map;
453         }
454                 
455         /**
456          * 转为字符串
457          * @param param
458          * @return
459          */
460         
461         private static String closeParam(Map<String,Object> param)
462         {
463             StringBuffer sb = new StringBuffer();
464             sb.append("<xml>");
465             Set<String> key = param.keySet();
466             for(String  k : key)
467             {
468                 sb.append("<" +k.toString().trim()+">" + param.get(k.trim()) + "</" + k.toString().trim() + ">");
469             }            
470             sb.append("</xml>");
471             return sb.toString();
472         }
473 }


  <6>将返回值生成二维码,前端wxpay.html页面,使用qrcode生成

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>微信支付 - $!{config.poweredby}</title>
<meta name="keywords" content="$!config.keywords" />
<meta name="description" content="$!config.description" />
<meta name="generator" content="$!{config.meta_generator}" />
<meta name="author" content="$!{config.meta_author}" />
<meta name="copyright" content="$!{config.copyRight}" />
<!-- <link href="$!webPath/resources/style/system/front/default/css/public.css" type="text/css" rel="stylesheet" /> -->
<link href="$!webPath/resources/style/system/front/default/css/goods.css" type="text/css" rel="stylesheet" />
<script type="text/javascript" src="$!webPath/resources/js/yjs/jquery.js"></script>
 <script type="text/javascript" src="$!webPath/resources/js/jquery.qrcode.min.js"></script>
      <link href="$!webPath/resources/style/system/front/default/webcss/zhuye/css.css" type="text/css" rel="stylesheet" />
 
        <script type="text/javascript">
            function utf16to8(str) {
                var out, i, len, c;
                out = "";
                len = str.length;
                for (i = 0; i < len; i++) {
                    c = str.charCodeAt(i);
                    if ((c >= 0x0001) && (c <= 0x007F)) {
                        out += str.charAt(i);
                    } else if (c > 0x07FF) {
                        out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
                        out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
                        out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
                    } else {
                        out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
                        out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
                    }
                }
                return out;
            }
            jQuery(function(){
                jQuery(#output).qrcode({
                          render    : "canvas",//也可以替换为table
                            width   : 200,
                            height  : 200,
                            text    : utf16to8("$!barCode")});
            })
        </script>
</head>
<body>

<div class="main" style="overflow:hidden;">
  
  <div class="payfor_box">
    <h3>微信支付</h3>
    <h5 style="color:#F00;">付款金额:¥$!order_total_price</h5>    
    <span class="payfor_textarea" id="output" style="color:#F00">
    
    </span> 
     <img src="$!webPath/resources/style/channel/images/wxpay.png"  />
     <h4>支付成功   <a href="$!webPath/index.htm">返回首页逛逛</a></h4>
     <h4>支付失败   <a href="$!webPath$!redirect">$!msg</a></h4>
     </div>
   

</div>

</body>
</html>

(3)前两步完成后,支付链接对应的二维码就可以自动生成,我们还需要对支付结果进行处理,微信回调方法:wxBuyerNotify

  1     /**
  2      * 微信支付回调
  3      * @param response
  4      * @param request
  5      */
  6     @RequestMapping("/wxBuyerNotify.htm")
  7     public void wxBuyerNotify(HttpServletResponse response,HttpServletRequest request)
  8     {
  9         //TODO 待完成
 10         String result ="<xml> <return_code><![CDATA[%s]]></return_code> <return_msg><![CDATA[%s]]></return_msg></xml>";
 11         
 12         StringBuffer xml = new StringBuffer();
 13         String temp = null;
 14         try
 15         {
 16             BufferedReader read = request.getReader();
 17             while((temp = read.readLine()) != null)
 18             {
 19                 xml.append(temp);
 20             }
 21             read.close();
 22             
 23         }
 24         catch(Exception e){}
 25         Map<String,String> param = ParseXml.parse(xml.toString());
 26         //验证是否微信回调
 27         if(checkSign(param))
 28         {
 29             //获取自定义返回值,此处定义的自定义返回值的格式为:付款类型,订单编号    
 30             String attach = param.get("attach");    
 31             
 32             String type = "" ;
 33             String order_id="" ;
 34             if (attach != null) {
 35                 String a[] = attach.split(",");
 36                 if (a[0] != null) {
 37                     type = a[0].trim();
 38                 }
 39                 if (a[1] != null) {
 40                     order_id = a[1].trim();
 41                 }
 42             }
 43             if(!StringUtils.isBlank(order_id) && !StringUtils.isBlank(type) )
 44             {
 45                 //签名,返回值,状态码判断之后,开始处理逻辑
 46                 OrderForm order = null;
 47                 Predeposit obj = null;
 48                 GoldRecord gold = null;
 49                 IntegralGoodsOrder ig_order = null;
 50                 if (type.equals("integral")) {
 51                     ig_order = this.integralGoodsOrderService.getObjById(CommUtil
 52                             .null2Long(order_id));
 53                 }
 54                 if (type.equals("cash")) {
 55                     obj = this.predepositService.getObjById(CommUtil
 56                             .null2Long(order_id));
 57                 }
 58                 if (type.equals("gold")) {
 59                     gold = this.goldRecordService.getObjById(CommUtil
 60                             .null2Long(order_id));
 61                 }
 62                 if (type.equals("goods") || type.equals("group")) {
 63                     order = this.orderFormService.getObjById(CommUtil
 64                             .null2Long(order_id));
 65                 }
 66                 
 67                 if (type.equals("cash")) {
 68                     obj.setPd_status(1);
 69                     obj.setPd_pay_status(2);
 70                     this.predepositService.update(obj);
 71                     User user = this.userService.getObjById(obj
 72                             .getPd_user().getId());
 73                     user.setAvailableBalance(BigDecimal.valueOf(CommUtil
 74                             .add(user.getAvailableBalance(),
 75                                     obj.getPd_amount())));
 76                     this.userService.update(user);
 77                 }
 78                 if (type.equals("goods") || type.equals("group")) {
 79                      if(order.getLiuCheng()==1){
 80                           if(order.getOrder_status()==10){
 81                               order.setOrder_status(18);////预售支付定金成功标志
 82                           }else if(order.getOrder_status()==18){
 83                               order.setOrder_status(20);////支付尾款成功,就是已付款
 84                           }
 85                      }
 86                      if(order.getLiuCheng()==0){
 87                          order.setOrder_status(20);////普通商品 ,20为已付款待发货
 88                             order.setPayTime(new Date());
 89                      }
 90                     
 91                     this.orderFormService.update(order);
 92                     if (order.getOrder_main() == 1
 93                             && !CommUtil.null2String(
 94                                     order.getChild_order_detail()).equals(
 95                                     "")) {// 同步完成子订单付款状态调整
 96                         List<Map> maps = this.orderFormTools
 97                                 .queryGoodsInfo(order
 98                                         .getChild_order_detail());
 99                         for (Map child_map : maps) {
100                             OrderForm child_order = this.orderFormService
101                                     .getObjById(CommUtil
102                                             .null2Long(child_map
103                                                     .get("order_id")));
104                             child_order.setOrder_status(20);
105                             this.orderFormService.update(child_order);
106                             // 向加盟商家发送付款成功短信提示,自营商品无需发送短信提示
107                             // 付款成功,发送短信提示
108                         }
109                     }
110                     // 如果是团购订单,则需呀执行团购订单相关流程及发送团购码
111                     if (order.getOrder_cat() == 2) {
112                         Calendar ca = Calendar.getInstance();
113                         ca.add(ca.DATE, this.configService.getSysConfig()
114                                 .getAuto_order_return());
115                         SimpleDateFormat bartDateFormat = new SimpleDateFormat(
116                                 "yyyy-MM-dd HH:mm:ss");
117                         String latertime = bartDateFormat.format(ca.getTime());
118                         order.setReturn_shipTime(CommUtil.formatDate(latertime));
119                         Map map = this.orderFormTools.queryGroupInfo(order
120                                 .getGroup_info());
121                         int count = CommUtil.null2Int(map.get("goods_count")
122                                 .toString());
123                         String goods_id = map.get("goods_id").toString();
124                         GroupLifeGoods goods = this.groupLifeGoodsService
125                                 .getObjById(CommUtil.null2Long(goods_id));
126                         /*        goods.setGroup_count(goods.getGroup_count()
127                                 - CommUtil.null2Int(count));
128                         this.groupLifeGoodsService.update(goods);*/
129                         int i = 0;
130                         List<String> code_list = new ArrayList();// 存放团购消费码
131                         /*User user = this.userService.getObjById(SecurityUserHolder
132                                 .getCurrentUser().getId());*/
133                         User user = this.userService.getObjById(CommUtil.null2Long(order.getUser_id()));
134                         Map params = new HashMap();
135                         params.put("mark", "wxpay");
136                         List<Payment> payments = this.paymentService.query(
137                                 "select obj from Payment obj where obj.mark=:mark", params,
138                                 -1, -1);
139                         String codes = "";
140                         System.out.println("微信支付团购消费码开始生成");
141                         while (i < count) {
142                             GroupInfo info = new GroupInfo();
143                             info.setAddTime(new Date());
144                             info.setLifeGoods(goods);
145                             info.setPayment(payments.get(0));
146                             info.setUser_id(CommUtil.null2Long(order.getUser_id()));
147                             info.setUser_name(CommUtil.null2String(order.getUser_name()));
148                             info.setOrder_id(order.getId());
149                             info.setGroup_sn(CommUtil.null2Long(order.getUser_id())
150                                     + CommUtil.formatTime("yyyyMMddHHmmss" + i,
151                                             new Date()));
152                             Calendar ca2 = Calendar.getInstance();
153                             ca2.add(ca2.DATE, this.configService.getSysConfig()
154                                     .getGrouplife_order_return());
155                             SimpleDateFormat bartDateFormat2 = new SimpleDateFormat(
156                                     "yyyy-MM-dd HH:mm:ss");
157                             String latertime2 = bartDateFormat2.format(ca2
158                                     .getTime());
159                             info.setRefund_Time(CommUtil.formatDate(latertime2));
160                             this.groupInfoService.save(info);
161                             codes = codes + info.getGroup_sn() + " ";
162                             code_list.add(info.getGroup_sn());
163                             i++;
164                         }
165                         if (order.getOrder_form() == 0) {
166                             Store store = this.storeService.getObjById(CommUtil
167                                     .null2Long(order.getStore_id()));
168                             if (store.getAgent_id() != null) {
169                                 User agent = this.userService.getObjById(store.getAgent_id());
170                                 agent.setAvailableBalance(BigDecimal.valueOf(CommUtil.add(agent.getAvailableBalance(), order.getAgent_commission_amount())));
171                                 this.userService.update(agent);
172                             }
173                             PayoffLog plog = new PayoffLog();
174                             plog.setPl_sn("pl"
175                                     + CommUtil.formatTime("yyyyMMddHHmmss",
176                                             new Date())
177                                     + store.getUser().getId());
178                             plog.setPl_info("团购码生成成功");
179                             plog.setAddTime(new Date());
180                             plog.setSeller(store.getUser());
181                             plog.setO_id(CommUtil.null2String(order.getId()));
182                             plog.setOrder_id(order.getOrder_id().toString());
183                             plog.setCommission_amount(
184                                     order.getCommission_amount());// 该订单总佣金费用
185                             plog.setAgent_commission_amount(
186                                     order.getAgent_commission_amount());// 该订单代理佣金费用
187                             // 将订单中group_info({})转换为List<Map>([{}])
188                             List<Map> Map_list = new ArrayList<Map>();
189                             Map group_map = this.orderFormTools
190                                     .queryGroupInfo(order.getGroup_info());
191                             Map_list.add(group_map);
192                             plog.setGoods_info(Json.toJson(Map_list,
193                                     JsonFormat.compact()));
194                             plog.setOrder_total_price(order.getTotalPrice());// 该订单总商品金额
195                             plog.setTotal_amount(BigDecimal.valueOf(CommUtil.subtract(order.getTotalPrice(), order.getCommission_amount())));// 该订单应结算金额:结算金额=订单总商品金额-总佣金费用
196                             this.payoffLogService.save(plog);
197                             System.out.println("微信支付团购消费码生成成功");
198                             store.setStore_sale_amount(BigDecimal
199                                     .valueOf(CommUtil.add(
200                                             order.getTotalPrice(),
201                                             store.getStore_sale_amount())));// 店铺本次结算总销售金额
202                             // 团购消费码,没有佣金,店铺总佣金不变,有佣金
203                             store.setStore_commission_amount(BigDecimal
204                                     .valueOf(CommUtil.add(
205                                             order.getCommission_amount(),
206                                             store.getStore_commission_amount())));
207                             store.setStore_payoff_amount(BigDecimal
208                                     .valueOf(CommUtil.add(
209                                             order.getTotalPrice(),
210                                             store.getStore_payoff_amount())));// 店铺本次结算总佣金
211                             this.storeService.update(store);
212                         }
213                         // 增加系统总销售金额
214                         SysConfig sc = this.configService.getSysConfig();
215                         sc.setPayoff_all_sale(BigDecimal.valueOf(CommUtil.add(
216                                 order.getTotalPrice(), sc.getPayoff_all_sale())));
217                         sc.setPayoff_all_commission(BigDecimal.valueOf(CommUtil.add(
218                                 order.getCommission_amount(), sc.getPayoff_all_commission())));
219                         this.configService.update(sc);
220                         // 更新lucene索引
221                         /*String goods_lucene_path = "";
222                         if (goods.getArea_id() != 0) {
223                             goods_lucene_path = System.getProperty("user.dir")
224                                     + File.separator + "luence"
225                                     + File.separator + "lifegoods"
226                                     + goods.getArea_id();
227                         } else {
228                             goods_lucene_path = System.getProperty("user.dir")
229                                     + File.separator + "luence"
230                                     + File.separator + "lifegoods";
231                         }
232                         File file = new File(goods_lucene_path);
233                         if (!file.exists()) {
234                             CommUtil.createFolder(goods_lucene_path);
235                         }
236                         LuceneUtil lucene = LuceneUtil.instance();
237                         lucene.setIndex_path(goods_lucene_path);
238                         lucene.update(CommUtil.null2String(goods.getId()),
239                                 luceneVoTools.updateLifeGoodsIndex(goods));*/
240                         String msg_content = "恭喜您成功购买团购"
241                                 + map.get("goods_name") + ",团购消费码分别为:" + codes
242                                 + "您可以到用户中心-我的生活购中查看消费码的使用情况";
243                         // 发送系统站内信给买家
244                         Message tobuyer_msg = new Message();
245                         tobuyer_msg.setAddTime(new Date());
246                         tobuyer_msg.setStatus(0);
247                         tobuyer_msg.setType(0);
248                         tobuyer_msg.setContent(msg_content);
249                         tobuyer_msg.setFromUser(this.userService
250                                 .getObjByProperty("userName", "admin"));
251                         tobuyer_msg.setToUser(user);
252                         this.messageService.save(tobuyer_msg);
253                         // 付款成功,发送短信团购消费码                    
254                     }
255                 //    this.update_goods_inventory(order,null);// 更新商品库存
256                     if (order.getOrder_cat() != 2) {
257                         
258                         List<Goods> goods_list = this.orderFormTools
259                                 .queryOfGoods(CommUtil.null2String(order
260                                         .getId()));
261                         for (Goods goods : goods_list) {
262                             // 造成搜索数据重复的原因
263                             String goods_lucene_path = null;
264                             if (goods.getGoods_type() == 0) { // 如果商品是自营商品
265                                 goods_lucene_path = System
266                                         .getProperty("user.dir")
267                                         + File.separator
268                                         + "luence"
269                                         + File.separator + "goods";
270                             } else { // 如果商品是店铺商品
271                                 if (goods.getGoods_store().getArea() != null) { // 店铺入驻到地区
272                                     goods_lucene_path = System
273                                             .getProperty("user.dir")
274                                             + File.separator
275                                             + "luence"
276                                             + File.separator
277                                             + "goods"
278                                             + goods.getGoods_store().getArea()
279                                                     .getId();
280                                 } else {
281                                     goods_lucene_path = System // 店铺入住到中国大区
282                                             .getProperty("user.dir")
283                                             + File.separator + "luence"
284                                             + File.separator + "goods_store";
285                                 }
286 
287                             }
288                             File file = new File(goods_lucene_path);
289                             if (!file.exists()) {
290                                 CommUtil.createFolder(goods_lucene_path);
291                             }
292                             LuceneUtil lucene = LuceneUtil.instance();
293                             lucene.setIndex_path(goods_lucene_path);
294                             lucene.update(CommUtil.null2String(goods.getId()),
295                                     luceneVoTools.updateGoodsIndex(goods));
296                         }
297                     }
298                     OrderFormLog ofl = new OrderFormLog();
299                     ofl.setAddTime(new Date());
300                     ofl.setLog_info("微信支付");
301                     ofl.setLog_user(SecurityUserHolder.getCurrentUser());
302                     ofl.setOf(order);
303                     this.orderFormLogService.save(ofl);
304                 }
305     
306                 if (type.equals("gold")) {
307                     gold.setGold_status(1);
308                     gold.setGold_pay_status(2);
309                     this.goldRecordService.update(gold);
310                     User user = this.userService.getObjById(gold
311                             .getGold_user().getId());
312                     user.setGold(user.getGold() + gold.getGold_count());
313                     this.userService.update(user);
314                     GoldLog log = new GoldLog();
315                     log.setAddTime(new Date());
316                     log.setGl_payment(gold.getGold_payment());
317                     log.setGl_content("微信支付");
318                     log.setGl_money(gold.getGold_money());
319                     log.setGl_count(gold.getGold_count());
320                     log.setGl_type(0);
321                     log.setGl_user(gold.getGold_user());
322                     log.setGr(gold);
323                     this.goldLogService.save(log);
324                 }
325                 if (type.equals("integral")) {
326                     ig_order.setIgo_status(20);
327                     ig_order.setIgo_pay_time(new Date());
328                     ig_order.setIgo_payment("wxpay");
329                     this.integralGoodsOrderService.update(ig_order);
330                     for (IntegralGoodsCart igc : ig_order.getIgo_gcs()) {
331                         IntegralGoods goods = igc.getGoods();
332                         goods.setIg_goods_count(goods.getIg_goods_count()
333                                 - igc.getCount());
334                         goods.setIg_exchange_count(goods
335                                 .getIg_exchange_count() + igc.getCount());
336                         this.integralGoodsService.update(goods);
337                     }
338                 }
339                 //处理业务逻辑结束
340                 result = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"  
341                             + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";  
342             }
343         }else{
344             result = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"  
345                       + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";  
346         }
347         //處理業務完畢,輸出結果
348         try
349         {
350             response.getOutputStream().write(result.getBytes());
351         }
352         catch(Exception ioe)
353         {
354             ioe.printStackTrace();
355         }
356         
357     }

           <-----------------------------结束------------------------------------------>

小结:支付环节步骤很复杂,但是根据官方API按步骤对接,可以有条理的进行对接
官方接口地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5,微信工具类请下载最新版

java对接微信支付

上一篇:微信小程序 - 提取字体图标与其优化


下一篇:微信朋友圈转发第三方网站带缩略图实现