国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

微信APP支付-Java后臺(tái)實(shí)現(xiàn)

2019-11-06 09:01:08
字體:
供稿:網(wǎng)友

1 注冊(cè)微信開放者平臺(tái)

開發(fā)者平臺(tái)地址:https://open.weixin.QQ.com/

2 成為開發(fā)者

這里寫圖片描述

3 上傳APP

這里寫圖片描述

4 開通微信支付功能

這里寫圖片描述

5 設(shè)置商戶號(hào)信息

APP 支付能力開通后,微信會(huì)給你一個(gè)商戶號(hào),用戶和密碼等信息。需要驗(yàn)證商戶信息,還需要設(shè)置一個(gè)加密的密鑰字段,這里就不一一細(xì)說了。

6 開發(fā)接口

微信APP支付接口,是很好調(diào)試的,(不像微信公眾平臺(tái),需要80端口),可以直接在本地就可以進(jìn)行調(diào)試。 具體業(yè)務(wù)就不細(xì)說,直接看代碼就懂了。

1 基礎(chǔ)信息配置
package com.qx.client.common.pay.weichart.config;import java.util.PRoperties;import com.tom.util.properties.PropertiesUtil;import com.tom.util.system.RSystemConfig;public class WeiChartConfig {   /**    * 預(yù)支付請(qǐng)求地址    */   public static final String  PrepayUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";   /**    * 查詢訂單地址    */   public static final String  OrderUrl = "https://api.mch.weixin.qq.com/pay/orderquery";   /**    * 關(guān)閉訂單地址    */   public static final String  CloSEOrderUrl = "https://api.mch.weixin.qq.com/pay/closeorder";   /**    * 申請(qǐng)退款地址    */   public static final String  RefundUrl = "https://api.mch.weixin.qq.com/secapi/pay/refund";   /**    * 查詢退款地址    */   public static final String  RefundQueryUrl = "https://api.mch.weixin.qq.com/pay/refundquery";   /**    * 下載賬單地址    */   public static final String  DownloadBillUrl = "https://api.mch.weixin.qq.com/pay/downloadbill";   /**    * 商戶APPID    */   public static final String  AppId = "wxabcdefghjjsdfsd";   /**    * 商戶賬戶 獲取支付能力后,從郵件中得到    */   public static final String  MchId = "13000000000001";   /**    * 商戶秘鑰  32位,在微信商戶平臺(tái)中設(shè)置    */   public static final String  AppSercret = "qx12345645778679789";   /**    * 服務(wù)器異步通知頁面路徑    */   public static String notify_url = getProperties().getProperty("notify_url");   /**    * 頁面跳轉(zhuǎn)同步通知頁面路徑    */   public static String return_url = getProperties().getProperty("return_url");   /**    * 退款通知地址    */   public static String refund_notify_url = getProperties().getProperty("refund_notify_url");   /**    * 退款需要證書文件,證書文件的地址    */   public static String refund_file_path = getProperties().getProperty("refund_file_path");   /**    * 商品名稱    */   public static String subject =  getProperties().getProperty("subject");   /**    * 商品描述    */   public static String body = getProperties().getProperty("body");   private static  Properties properties;   public static synchronized Properties getProperties(){      if(properties == null){         String path = System.getenv(RSystemConfig.KEY_WEB_HOME_CONF) + "/weichart.properties";         properties = PropertiesUtil.getInstance().getProperties(path);      }      return properties;   }}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969712345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
2 http /https請(qǐng)求的工具類

其中有需要證書的,也有不需要證書的。 證書是在需要退款接口的時(shí)候需要使用,直接把證書放在服務(wù)器上,然后傳路徑

package com.qx.client.common.pay.weichart.util.httpClient;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.net.MalformedURLException;import java.net.URL;import java.net.URLConnection;import java.security.KeyStore;import java.util.Map;import javax.net.ssl.SSLContext;import org.apache.commons.httpclient.HttpClient;import org.apache.commons.httpclient.methods.PostMethod;import org.apache.commons.httpclient.methods.StringRequestEntity;import org.apache.commons.httpclient.params.HttpMethodParams;import org.apache.http.HttpEntity;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpPost;import org.apache.http.conn.ssl.SSLConnectionSocketFactory;import org.apache.http.conn.ssl.SSLContexts;import org.apache.http.entity.StringEntity;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.apache.http.util.EntityUtils;public class HttpClientUtil{   public static String post(String url,                             Map<String, String> headMap,                             Map<String, String> params){      try{         HttpClient httpclient = new HttpClient();         httpclient.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");         PostMethod httpPost = new PostMethod(url);         if(null != headMap){            for(String key : headMap.keySet()){               httpPost.setRequestHeader(key, headMap.get(key));            }         }         if(null != params){            for(String pkey : params.keySet()){               httpPost.addParameter(pkey, params.get(pkey));            }         }         httpclient.executeMethod(httpPost);         BufferedReader reader = new BufferedReader(new InputStreamReader(httpPost.getResponseBodyAsStream()));         StringBuffer stringBuffer = new StringBuffer();         String str = "";         while((str = reader.readLine()) != null){            stringBuffer.append(str);         }         reader.close();         return stringBuffer.toString();      }catch(Exception e){         e.printStackTrace();      }      return null;   }   public static String postHttplient(String url,                                      String xmlInfo){      try{         HttpClient httpclient = new HttpClient();         httpclient.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");         PostMethod httpPost = new PostMethod(url);         httpPost.setRequestEntity(new StringRequestEntity(xmlInfo));         httpclient.executeMethod(httpPost);         BufferedReader reader = new BufferedReader(new InputStreamReader(httpPost.getResponseBodyAsStream()));         StringBuffer stringBuffer = new StringBuffer();         String str = "";         while((str = reader.readLine()) != null){            stringBuffer.append(str);         }         reader.close();         return stringBuffer.toString();      }catch(Exception e){         e.printStackTrace();      }      return null;   }   /**    * 需要加密執(zhí)行的    * @param url    * @param xmlInfo    * @return    * @throws Exception     */   public static String postHttplientNeedSSL(String url,                                             String xmlInfo,                                             String cretPath,                                             String mrchId)         throws Exception{      //選擇初始化密鑰文件格式      KeyStore keyStore = KeyStore.getInstance("PKCS12");      //得到密鑰文件流      FileInputStream instream = new FileInputStream(new File(cretPath));      try{         //用商戶的ID 來解讀文件         keyStore.load(instream, mrchId.toCharArray());      }finally{         instream.close();      }      //用商戶的ID 來加載      SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mrchId.toCharArray()).build();      // Allow TLSv1 protocol only      SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);      //用最新的httpclient 加載密鑰      CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();      StringBuffer ret = new StringBuffer();      try{         HttpPost httpPost = new HttpPost(url);         httpPost.setEntity(new StringEntity(xmlInfo));         CloseableHttpResponse response = httpclient.execute(httpPost);         try{            HttpEntity entity = response.getEntity();            if(entity != null){               BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));               String text;               while((text = bufferedReader.readLine()) != null){                  ret.append(text);               }            }            EntityUtils.consume(entity);         }finally{            response.close();         }      }finally{         httpclient.close();      }      return ret.toString();   }   public static String postHtpps(String urlStr,                                  String xmlInfo){      try{         URL url = new URL(urlStr);         URLConnection con = url.openConnection();         con.setDoOutput(true);         con.setRequestProperty("Pragma:", "no-cache");         con.setRequestProperty("Cache-Control", "no-cache");         con.setRequestProperty("Content-Type", "text/xml;charset=utf-8");         OutputStreamWriter out = new OutputStreamWriter(con.getOutputStream(), "utf-8");         out.write(xmlInfo);         out.flush();         out.close();         BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));         StringBuffer lines = new StringBuffer();         String line = "";         for(line = br.readLine(); line != null; line = br.readLine()){            lines.append(line);         }         return lines.toString();      }catch(MalformedURLException e){         e.printStackTrace();      }catch(IOException e){         e.printStackTrace();      }      return null;   }}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
4 調(diào)用API接口

其中包含 XML生成,和解析XML,請(qǐng)求參數(shù)字典排序,拼接密鑰,md5加密

package com.qx.client.common.pay.weichart.util;import java.net.InetAddress;import java.net.UnknownHostException;import java.util.Arrays;import java.util.Date;import java.util.HashMap;import java.util.Map;import java.util.Random;import java.util.Set;import org.mobj.com.encoding.RMd5;import org.mobj.com.xml.FXmlDocument;import org.mobj.com.xml.FXmlNode;import org.mobj.com.xml.FXmlNodes;import com.qx.client.common.pay.weichart.config.WeiChartConfig;import com.qx.client.common.pay.weichart.util.httpClient.HttpClientUtil;public class WeiChartUtil{   /**    * 返回狀態(tài)碼    */   public static final String ReturnCode = "return_code";   /**    * 返回信息    */   public static final String ReturnMsg = "return_msg";   /**    * 業(yè)務(wù)結(jié)果    */   public static final String ResultCode = "result_code";   /**    * 預(yù)支付交易會(huì)話標(biāo)識(shí)    */   public static final String PrepayId = "prepay_id";   /**    * 得到微信預(yù)付單的返回ID    * @param orderId  商戶自己的訂單號(hào)    * @param totalFee  總金額  (分)    * @return    */   public static Map<String, String> getPreyId(String orderId,                                  String totalFee){      Map<String, String> reqMap = new HashMap<String, String>();      reqMap.put("appid", WeiChartConfig.AppId);      reqMap.put("mch_id", WeiChartConfig.MchId);      reqMap.put("nonce_str", getRandomString());      reqMap.put("body", WeiChartConfig.body);      //reqMap.put("detail", WeiChartConfig.subject); //非必填      //reqMap.put("attach", "附加數(shù)據(jù)"); //非必填      reqMap.put("out_trade_no", orderId); //商戶系統(tǒng)內(nèi)部的訂單號(hào),      reqMap.put("total_fee", totalFee); //訂單總金額,單位為分      reqMap.put("spbill_create_ip", getHostIp()); //用戶端實(shí)際ip      // reqMap.put("time_start", "172.16.40.18"); //交易起始時(shí)間 非必填      // reqMap.put("time_expire", "172.16.40.18"); //交易結(jié)束時(shí)間  非必填      // reqMap.put("goods_tag", "172.16.40.18"); //商品標(biāo)記 非必填      reqMap.put("notify_url", WeiChartConfig.notify_url); //通知地址      reqMap.put("trade_type", "APP"); //交易類型      //reqMap.put("limit_pay", "no_credit"); //指定支付方式,no_credit 指定不能使用信用卡支  非必填      reqMap.put("sign", getSign(reqMap));      String reqStr = creatXml(reqMap);      String retStr = HttpClientUtil.postHttplient(WeiChartConfig.PrepayUrl, reqStr);      return getInfoByXml(retStr);   }   /**    * 關(guān)閉訂單    * @param orderId  商戶自己的訂單號(hào)    * @return    */   public static Map<String, String> closeOrder(String orderId){      Map<String, String> reqMap = new HashMap<String, String>();      reqMap.put("appid", WeiChartConfig.AppId);      reqMap.put("mch_id", WeiChartConfig.MchId);      reqMap.put("nonce_str", getRandomString());      reqMap.put("out_trade_no", orderId); //商戶系統(tǒng)內(nèi)部的訂單號(hào),      reqMap.put("sign", getSign(reqMap));      String reqStr = creatXml(reqMap);      String retStr = HttpClientUtil.postHttplient(WeiChartConfig.CloseOrderUrl, reqStr);      return getInfoByXml(retStr);   }   /**    * 查詢訂單    * @param orderId 商戶自己的訂單號(hào)    * @return    */   public static String getOrder(String orderId){      Map<String, String> reqMap = new HashMap<String, String>();      reqMap.put("appid", WeiChartConfig.AppId);      reqMap.put("mch_id", WeiChartConfig.MchId);      reqMap.put("nonce_str", getRandomString());      reqMap.put("out_trade_no", orderId); //商戶系統(tǒng)內(nèi)部的訂單號(hào),      reqMap.put("sign", getSign(reqMap));      String reqStr = creatXml(reqMap);      String retStr = HttpClientUtil.postHttplient(WeiChartConfig.OrderUrl, reqStr);      return retStr;   }   /**    * 退款    * @param orderId  商戶訂單號(hào)    * @param refundId  退款單號(hào)    * @param totralFee 總金額(分)    * @param refundFee 退款金額(分)    * @param opUserId 操作員ID    * @return    */   public static Map<String, String> refundWei(String orderId,String refundId,String totralFee,String refundFee,String opUserId){      Map<String, String> reqMap = new HashMap<String, String>();      reqMap.put("appid", WeiChartConfig.AppId);      reqMap.put("mch_id", WeiChartConfig.MchId);      reqMap.put("nonce_str", getRandomString());      reqMap.put("out_trade_no", orderId); //商戶系統(tǒng)內(nèi)部的訂單號(hào),      reqMap.put("out_refund_no", refundId); //商戶退款單號(hào)      reqMap.put("total_fee", totralFee); //總金額      reqMap.put("refund_fee", refundFee); //退款金額      reqMap.put("op_user_id", opUserId); //操作員      reqMap.put("sign", getSign(reqMap));      String reqStr = creatXml(reqMap);      String retStr = "";      try{         retStr = HttpClientUtil.postHttplientNeedSSL(WeiChartConfig.RefundUrl, reqStr, WeiChartConfig.refund_file_path, WeiChartConfig.MchId);      }catch(Exception e){         e.printStackTrace();         return null;      }      return getInfoByXml(retStr);   }   /**    * 退款查詢    * @param refundId  退款單號(hào)    * @return    */   public static Map<String, String> getRefundWeiInfo(String refundId){      Map<String, String> reqMap = new HashMap<String, String>();      reqMap.put("appid", WeiChartConfig.AppId);      reqMap.put("mch_id", WeiChartConfig.MchId);      reqMap.put("nonce_str", getRandomString());      reqMap.put("out_refund_no", refundId); //商戶退款單號(hào)      reqMap.put("sign", getSign(reqMap));      String reqStr = creatXml(reqMap);      String retStr = HttpClientUtil.postHttplient(WeiChartConfig.RefundQueryUrl, reqStr);      return getInfoByXml(retStr);   }   /**    * 傳入map  生成頭為XML的xml字符串,例:<xml><key>123</key></xml>    * @param reqMap    * @return    */   public static String creatXml(Map<String, String> reqMap){      Set<String> set = reqMap.keySet();      FXmlNode rootXml = new FXmlNode();      rootXml.setName("xml");      for(String key : set){         rootXml.createNode(key, reqMap.get(key));      }      return rootXml.xml().toString();   }   /**    * 得到加密值    * @param map    * @return    */   public static String getSign(Map<String, String> map){      String[] keys = map.keySet().toArray(new String[0]);      Arrays.sort(keys);      StringBuffer reqStr = new StringBuffer();      for(String key : keys){         String v = map.get(key);         if(v != null && !v.equals("")){            reqStr.append(key).append("=").append(v).append("&");         }      }      reqStr.append("key").append("=").append(WeiChartConfig.AppSercret);      //MD5加密      return RMd5.encode(reqStr.toString()).toUpperCase();   }   /**    * 得到10 位的時(shí)間戳    * 如果在JAVA上轉(zhuǎn)換為時(shí)間要在后面補(bǔ)上三個(gè)0     * @return    */   public static String getTenTimes(){      String t = new Date().getTime()+"";      t = t.substring(0, t.length()-3);      return t;   }   /**    * 得到隨機(jī)字符串    * @param length    * @return    */   public static String getRandomString(){      int length = 32;      String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";      Random random = new Random();      StringBuffer sb = new StringBuffer();      for(int i = 0; i < length; ++i){         int number = random.nextInt(62);//[0,62)           sb.append(str.charAt(number));      }      return sb.toString();   }   /**    * 得到本地機(jī)器的IP    * @return    */   private static String getHostIp(){      String ip = "";      try{         ip = InetAddress.getLocalHost().getHostAddress();      }catch(UnknownHostException e){         e.printStackTrace();      }      return ip;   }   /**    * 將XML轉(zhuǎn)換為Map 驗(yàn)證加密算法 然后返回    * @param xml    * @return    */   public static Map<String, String>  getInfoByXml(String xml){      try{         FXmlDocument xdoc = new FXmlDocument();         FXmlNode nodeRoot = xdoc.formatStringToXml(xml);         FXmlNodes allNodes =  nodeRoot.allNodes();         Map<String, String> map = new HashMap<String, String>();         for(FXmlNode fXmlNode : allNodes){            map.put(fXmlNode.name(), fXmlNode.text());         }         //對(duì)返回結(jié)果做校驗(yàn).去除sign 字段再去加密         String retSign = map.get("sign");         map.remove("sign");         String rightSing = getSign(map);         if(rightSing.equals(retSign)){            return map;         }      }catch(Exception e){         return null;      }      return null;   }   /**    * 將金額轉(zhuǎn)換成分    * @param fee 元格式的    * @return 分    */   public static String changeToFen(Double fee){      String priceStr = "";      if(fee != null){          int p = (int)(fee * 100); //價(jià)格變?yōu)榉?         priceStr = Integer.toString(p);      }      return priceStr;   }}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282

在微信支付的調(diào)試過程中,發(fā)現(xiàn)了一個(gè)困擾了很長(zhǎng)時(shí)間的BUG,或者說是一個(gè)問題。 就是微信請(qǐng)求預(yù)支付的時(shí)候如果傳了中文,就是body中給的是中文,就會(huì)報(bào)body不是UTF-8格式。如果強(qiáng)行對(duì)字段進(jìn)行編碼,又會(huì)報(bào) 加密錯(cuò)誤。

但是這不是最主要的讓人困擾的地方,最讓我煩惱的是,我用本地的JDK調(diào)試的時(shí)候,它是OK 的。 但是用TOMCAT 部署的時(shí)候 卻一直都不行

在網(wǎng)上有很多的說法,有的說,對(duì)body 進(jìn)行編碼轉(zhuǎn)換UTF-8,有的說對(duì)整個(gè)請(qǐng)求的XML,進(jìn)行編碼。

還有的說編碼格式用統(tǒng)一的。iso900…等等,巴拉巴拉的。。 反正我都不行。

最后在大神的幫助下,慢慢梳理,對(duì)發(fā)送請(qǐng)求的post方法上面想辦法。 然后就是下面的 這句關(guān)鍵

public static String postHtpps(String urlStr,                                  String xmlInfo){      try{         URL url = new URL(urlStr);         URLConnection con = url.openConnection();         con.setDoOutput(true);         con.setRequestProperty("Pragma:", "no-cache");         con.setRequestProperty("Cache-Control", "no-cache");         con.setRequestProperty("Content-Type", "text/xml;charset=utf-8");         //在輸入流里面進(jìn)行轉(zhuǎn)碼,是最重要的         OutputStreamWriter out = new OutputStreamWriter(con.getOutputStream(), "utf-8");         out.write(xmlInfo);         out.flush();         out.close();         BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));         StringBuffer lines = new StringBuffer();         String line = "";         for(line = br.readLine(); line != null; line = br.readLine()){            lines.append(line);         }         return lines.toString();      }catch(MalformedURLException e){         e.printStackTrace();      }catch(IOException e){         e.printStackTrace();      }      return null;   }}
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 新闻| 开阳县| 渝北区| 安西县| 朝阳区| 廊坊市| 张北县| 嘉定区| 乐亭县| 寿阳县| 清徐县| 金山区| 太保市| 唐山市| 广南县| 南溪县| 宁津县| 鄂伦春自治旗| 昌都县| 宁阳县| 枣庄市| 静海县| 罗江县| 固原市| 沈阳市| 五原县| 宁晋县| 乌拉特后旗| 包头市| 保亭| 廊坊市| 赞皇县| 沐川县| 青田县| 万年县| 抚远县| 绵竹市| 延庆县| 凉山| 湄潭县| 靖边县|