Baru -baru ini, saya telah terpapar beberapa hal tentang pembayaran WeChat dalam pekerjaan saya. Saya melihat bahwa demo yang saya berikan adalah semua versi PHP, dan saya benar -benar tidak puas dengan dokumen pembayaran WeChat. Setelah mengalami banyak jebakan, saya menganggur untuk membuat ringkasan.
1. Persiapan
Untuk mengembangkan WeChat, Anda harus terlebih dahulu melamar akun publik. Setelah aplikasi berhasil, Anda akan dikirimkan kepada Anda melalui email. Akun publik berisi dokumen pengembangan, informasi yang diperlukan selama pengembangan, dan permintaan data untuk pengujian.
2. Alat
1. MD5 Kelas Alat Enkripsi
Paket com.pay.utils.weixin; import java.security.messagedigest; kelas publik md5util {public final static string md5 (string s) {char hexdigits [] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; coba {byte [] btinput = s.getbytes (); // Dapatkan objek MessageDigest dari algoritma MD5 Digest MessageSpedIgest mdinst = MessageSageTigest.getInstance ("md5"); // perbarui pencernaan mdinst.update (btinput); // Dapatkan byte ciphertext [] md = mdinst.digest (); // Konversikan ciphertext menjadi hex string bentuk int j = md.length; char str [] = char baru [j * 2]; int k = 0; untuk (int i = 0; i <j; i ++) {byte byte0 = md [i]; str [k ++] = hexdigits [byte0 >>> 4 & 0xf]; str [k ++] = hexdigits [byte0 & 0xf]; } return new string (str); } catch (Exception e) {E.PrintStackTrace (); kembali nol; }}}2. Kelas Alat Commonutil , digunakan untuk mengganti XML yang diperlukan untuk WeChat. Pengembalian string baru berikut (xml.toString (). GetBytes (), "iso8859-1"); Ubah UTF-8 di kelas alat menjadi ISO8859-1, jika tidak teks Cina dalam urutan WeChat akan tampak kacau, dan dapat ditampilkan dengan benar setelah perubahan.
package com.pay.utils.weixin;import java.io.UnsupportedEncodingException;import java.net.URLEncoder;import java.util.*;import java.util.Map.Entry;public class CommonUtil { public static String CreateNoncestr(int length) { String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSUVWXYZ0123456789"; String res = ""; untuk (int i = 0; i <panjang; i ++) {acak rd = acak baru (); res += chars.indexof (rd.nextInt (chars.length () - 1)); } return res; } public static string createNonceStr () {string chars = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789"; String res = ""; untuk (int i = 0; i <16; i ++) {acak rd = acak baru (); res += chars.charat (rd.nextint (chars.length () - 1)); } return res; } public static String formatQueryParAmap (hashMap <string, string> parameter) melempar sdkruntiMeException {string buff = ""; coba {list <map.entry <string, string >> infoids = new arraylist <map.entry <string, string >> (parameter.entryset ()); Collections.sort (infoids, pembanding baru <map.entry <string, string >> () {public int compare (map.entry <string, string> o1, map.entry <string, string> o2) {return (o1.getKey ()). Tostring (). Compareto (o2.getKey ();}); untuk (int i = 0; i <infoids.size (); i ++) {map.entry <string, string> item = infoids.get (i); if (item.getKey ()! = "") {buff + = item.getKey () + "=" + urlencoder.encode (item.getValue (), "UTF-8") + "&"; }} if (buff.isempty () == false) {buff = Buff.substring (0, buff.length () - 1); }} catch (Exception e) {lempar SDKRunTimeException baru (e.getMessage ()); } return buff; } public static String formatBizQueryParAmap (hashMap <string, string> paramap, boolean urlencode) melempar sdkruntiMeException {string buff = ""; coba {list <map.entry <string, string >> infoids = new arraylist <map.entry <string, string >> (paramap.entryset ()); Collections.sort (infoids, pembanding baru <map.entry <string, string >> () {public int compare (map.entry <string, string> o1, map.entry <string, string> o2) {return (o1.getKey ()). Tostring (). Compareto (o2.getKey ();}); untuk (int i = 0; i <infoids.size (); i ++) {map.entry <string, string> item = infoids.get (i); //System.out.println (item.getKey ()); if (item.getKey ()! = "") {string key = item.getKey (); String val = item.getValue (); if (urlencode) {val = urlencoder.encode (val, "UTF-8"); } buff + = key.tolowercase () + "=" + val + "&"; }} if (buff.isempty () == false) {buff = Buff.substring (0, buff.length () - 1); }} catch (Exception e) {lempar SDKRunTimeException baru (e.getMessage ()); } return buff; } public static boolean isNumeric (string str) {if (str.matches ("// d *")) {return true; } else {return false; }} public static string arraytoxml (hashMap <string, string> arr) {string xml = "<xml>"; Iterator <entry <string, string >> iter = arr.entryset (). Iterator (); while (iter.hasnext ()) {entri <string, string> entri = iter.next (); String key = entry.getKey (); String val = entry.getValue (); if (isNumeric (val)) {xml + = "<" + key + ">" + val + "</" + key + ">"; } else xml + = "<" + key + "> <! [cdata [" + val + "]]> </" + key + ">"; } xml += "</xml>"; coba {return new string (xml.toString (). getBytes (), "iso8859-1"); } catch (UnsupportedEncodingException e) {// TODO Auto-Enchenerated Catch Block E.PrintStackTrace (); } kembali ""; }}3.ClientCustomsSL Kelas Alat , digunakan untuk menghasilkan tanda dan membuat paket pesanan weChat com.pay.utils.weixin;
impor java.util.arraylist; impor java.util.collections; impor java.util.util. */kelas publik clientCustomssl {public static String getBizSign (hashMap <string, string> bizoBj) melempar sdkruntimeException {hashmap <string, string> bizparameters = hashmap baru <string, string> (); Daftar <map.entry <string, string >> infoids = new arraylist <map.entry <string, string >> (bizobj.entryset ()); System.out.println (infoids); Collections.sort (infoids, pembanding baru <map.entry <string, string >> () {public int compare (map.entry <string, string> o1, map.entry <string, string> o2) {return (o1.getKey ()). ToString (). Compareto (o2.getKey ();} () ;- --- --- –u- "(o2.pexoing. System.out.println (infoids); untuk (int i = 0; i <infoids.size (); i ++) {map.entry <string, string> item = infoids.get (i); if (item.getKey ()! = "") {bizparameters.put (item.getKey (). TolowerCase (), item.getValue ()); }} //bizparameters.put("key "," 1234567812345678123456781234567812345671 "); String BizString = Commonutil.FormatBizQueryParamap (BizParameters, False); BizString += "& Key = 123456781234567812345671"; System.out.println ("***************"); System.out.println (BizString); // return sha1util.sha1 (BizString); return md5util.md5 (BizString); } /** * WeChat create order* @param nonceStr * @param orderDescribe * @param orderNo * @param price * @param timeStart * @param timeExpire * @return * @throws SDKRuntimeException */ public static String CreateNativePackage(String nonceStr,String orderDescribe,String orderNo,String price,String timeStart,String timeExpire) throws SdkruntiMeException {hashMap <string, string> nativeObj = new HashMap <string, string> (); NativeObj.put ("appid", "lihat akun publik"); // ID Akun Publik NativeObj.put ("MCH_ID", "Lihat Email"); // nomor pedagang nativeObj.put ("nonce_str", noncestr); // string acak nativeObj.put ("body", orderdescribe); // Deskripsi Produk NativeObj.put ("lampirkan", "tradeno"); // data terlampir nativeObj.put ("out_trade_no", orderno); // Nomor Pesanan Pedagang (Global Unik) NativeObj.put ("Total_Fee", Harga); // Jumlah total (unit adalah sen, tidak dapat diambil dengan titik desimal) NativeObj.put ("spbill_create_ip", "192.168.0.144"); // terminal ip nativeObj.put ("time_start", timestArt); // Transaksi Mulai Waktu NativeObj.put ("Time_Expire", TimeExPire); // transaksi akhir waktu nativeObj.put ("notify_url", customizedPropertyplaceHolderConfigurer.getContextProperty ("wxUrl")+"/weixin_callback/weixincallback/init.action"); // alamat pemberitahuan callback nativeObj.put ("trade_type", "asli"); // Tipe Transaksi String Sign = GetBizSign (NativeObj); NativeObj.put ("Sign", Sign.touppercase ()); return commoril.arraytoxml (nativeObj); } /*** WeChat order payment query* @param nonceStr* @param orderDescribe* @param orderNo* @param price* @param timeStart* @param timeExpire* @return* @throws SDKRuntimeException*/public static String SearchNativePackage(String transactionId,String outTradeNo,String nonceStr) throws SDKRuntimeException {HashMap <String, String> NativeObj = new HashMap <String, String> (); nativeObj.put ("appId", "lihat akun publik"); // akun publik idnativeObj.put ("mch_id", "lihat email"); // nomor pedagang nativeObj.put ("nonce_str", noncestr); // string acak if (! Stringutils.isempty (transactionId)) {nativeObj.put ("transaction_id", transactionId); } if (! stringutils.isempty (outtradeno)) {nativeObj.put ("out_trade_no", outtradeno); // string acak} string Sign = getBizSign (nativeObj); nativeObj.put ("Sign", Sign.touppercase ()); return commoril.arraytoxml (nativeObj); /*** WeChat refund* @param outTradeNo* @param outRefundNo * @param totalFee* @param totalFee* @param refundFee* @return* @throws SDKRuntimeException*/public static String RefundNativePackage(String outTradeNo,String outRefundNo,String totalFee,String refundFee,String nonceStr) throws SdkRunTimeException {HashMap <String, String> NativeObj = new HashMap <String, String> (); nativeObj.put ("appId", "lihat akun publik"); // akun publik idnativeObj.put ("mch_id", "lihat email"); // nomor pedagang nativeObj.put ("mch_id", "lihat email"); // nomor pedagang nativeObj.put ("nonce" noncestr "); NativeObj.put ("out_trade_no", outtradeno); // nomor pesanan pedagang (global unik) nativeObj.put ("out_refund_no", outrefundno); // nomor pesanan pengembalian uang (global) (unik "poin native," total), total native), TOTAL, TOTAL_FEE ", TOTALFEE); pengembalian uang); // jumlah pengembalian uang (unit dalam sen, tidak dapat mengambil poin desimal) nativeObj.put ("op_user_id", "mail"); String Sign = getBizSign (NativeObj); NativeObj.put ("tanda", tanda CreateJsApiPackage(String nonceStr,String orderDescribe,String orderNo,String price,String timeStart,String timeExpire,String openId) throws SDKRuntimeException {HashMap<String, String> nativeObj = new HashMap<String, String>();nativeObj.put("appid", "see public account");//Public account IdnativeObj.put("openid", OpenId); // akun publik idnativeObj.put ("mch_id", "lihat email") // nomor pedagang nativeObj.put ("nonce_str", noncestr); // string acak nativeObj.put ("body", orderdescribe); // Deskripsi Produk Native.put.put ("lampiran", "tradeno");//looks native. orderno); // nomor pesanan pedagang (global unik) nativeObj.put ("total_fee", harga); // jumlah total (unit adalah sen, tidak dapat mengambil poin desimal) nativeObj.put ("spbill_create_ip", "192.168.0.144"); // terminal ipnativeObj.put time_start "); nativeObj.put("time_expire", timeExpire)//Transaction end time nativeObj.put("notify_url",CustomizedPropertyPlaceholderConfigurer.getContextProperty("wxurl")+"/weixin_callback/weixinCallback/init.action");//Notification address nativeObj.put("trade_type", "JSAPI"); // Tipe Transaksi String Sign = GetBizSign (NativeObj); NativeObj.put ("Sign", Sign.touppercase ()); return CommonUtil.ArrayToXml(nativeObj);}/*** Close order on WeChat* @param nonceStr* @param orderDescribe* @param orderNo* @param price* @param timeStart* @param timeExpire* @param openId* @return* @throws SDKRuntimeException*/public static String CreateCloseOrder(String outTradeNo,String nonceStr) Melempar SdkrunTimeException {HashMap <String, String> NativeObj = new HashMap <String, String> (); NativeObj.put ("AppID", "Lihat Akun Publik"); // Akun Publik Idnative.put ("MCH_ID", "Lihat Email"); // angka public nativeObj.put ("MCH_ID", "Lihat email"); // angka public nativeObj.put ("MCH_ID", "lihat email"); // public numberObj.put ("MCH_ID", "lihat email"); // public numberoBj.put ("mch_id" Number (Global Unik) NativeObj.put ("NONCE_STR", NONCEST); // Random String String Sign = GetBizSign (NativeObj); NativeObj.put ("Sign", Sign.touppercase ()); return commonutil.arraytoxml (nativeObj);}} 4. Hubungi Antarmuka Pembayaran WeChat
Paket com.pay.controller.weixin; import java.io.file; import java.io.fileInputStream; import java.security.keystore; import java.text.simpledateFormat; impor java.util.date; impor java.util.list. javax.servlet.http.httpservletrequest; impor javax.servlet.http.httpservletResponse; impor net.sf.json.jsonarray; import net.sf.json.json.jsonject; org.apache.http.client.methods.closeableHtpresponse; import org.apache.http.client.methods.htpppost; org.apache.http.conn.ssl.sslconnectionocketfactory; impor org.apache.htslonn.sslconnectionocketor; org.apache.http.entity.stringentity; impor org.apache.http.impl.client.closeableHttpClient; impor org.apache.http.impl.client.httpClients; impor org.apache.http.util.entityutils; org.dom4j.documenthelper; impor org.dom4j.element; impor org.dom4j.io.saxreader; impor org.springframework.beans.factory.annotation.autowired; impor org.springframework.http.httpstatus; org.springframework.web.bind.annotation.requestbody; impor org.springframework.web.bind.annotation.requestmapping; impor org.springframework.web.bind.annotation.requestmethod; impor org.springframew.wind.bind.bind.bind.nannotion; org.springframework.web.bind.annotation.restcontroller; import com.pay.bo.payhistants.import com.pay.constants.payhistorypaystatus; import com.pay.conservicePaysorypaytype; impor com.pay.service.wexinpaysorypaypay; com.pay.utils.weixin.clientcustomssl; import com.pay.utils.weixin.closeweixinOrderutils; import com.pay.utils.weixin.customizedPropertyplaceFigerFigurer@restcontroller@requestMapping ("/pay") publice class publice WeixInpayservice; Private Static Long Standardtime = 1662652800000L; /** * Return the url that generates the QR code * @param request * @param response * @return */ @RequestMapping(value="/getUrl",method=RequestMethod.POST) @ResponseStatus(HttpStatus.OK) public Object getUrl(HttpServletResponse response,@RequestBody String body){ try{ JSONObject jsonO = JsonObject.fromObject (body); Payhist ph = null; // daftar <peta <string, objek >> td = weixInpayservice.gettrade (orderno); Tanggal dt = tanggal baru (); SimpleDateFormat SDF = new SimpleDateFormat ("yyyymmddhhmmss"); String noncestr = sdf.format (dt) .toString (); Tanggal sekarang = tanggal baru (); String tradepayno = jsono.get ("orderno"). ToString ()+string.format ("%10d", standardtime - now.getTime ()). Substring (0, 10); System.out.println ("订单标号 ordno ======="+jsono.get ("orderno"). ToString ()); System.out.println ("10 位随机数 ======="+String.Format ("%10D", StandardTime - Now.getTime ()). Substring (0, 10)); String Price = Math.round (float.ValueOf (jsono.get ("harga"). ToString ())*100)+""; Long timeexpirestrold = dt.getTime (); Long timeNew = long.parselong (customizedPropertyplaceHolderConfigurer.getContextProperty ("weixin.send2finish.overtime"). ToString ()); Long timeexpirenew = timeexpirestrold+timeNew; Tanggal dtTimeExPire = Tanggal baru (TimeExpireNew); SimpleDateFormat dtsdf = new SimpleDateFormat ("yyyymmddhhmmss"); String timeExPire = dtsdf.format (dttimeExPire) .toString (); System.out.println ("noncestr =="+noncestr); System.out.println ("orderno =="+jsono.get ("orderno"). ToString ()); System.out.println ("Harga =="+Harga); System.out.println ("timestArt =="+noncestr); System.out.println ("TimeExPire =="+TimeExPire); JSONObject result = (jsonObject) setUrl (noncestr, "order", tradepayno, price, noncestr, timeexPire); if (result.get ("status"). toString (). Equals ("Success")) {ph = new payhist (); ph.settradepayurl (result.getString ("weixInpayurl")); // Bidang ini adalah tautan pembayaran. Anda dapat menghasilkan kode QR untuk memindai kode untuk membayar ph.setpaytradeno (jsono.get ("orderno"). Tostring ()); ph.settradepayno (tradepayno); ph.setpaystatus (payhistorypaystatus.wechat_pay_status_wait); ph.setPayType (payhistorypaytype.wechat); ph.setAppKey (jsono.getString ("appkey"). tostring ()); ph.setpayamount (harga); result.put ("paytradeno", ph.getpaytradeno ()); result.put ("tradepayno", ph.gettradepayno ()); result.put ("paystatus", ph.getpaystatus ()); result.put ("paytype", ph.getPayType ()); } hasil pengembalian; } catch (Exception e) {E.PrintStackTrace (); JSONObject hasil = jsonObject () baru; result.put ("status", "error"); result.put ("msg", e.getMessage ()); // return result.toString (); } return null; } public Object SetUrl (String noncestr, String orderDescribe, String orderno, String Price, String TimestArt, String TimeExPire) {coba {keystore keystore = keystore.getInstance ("pkcs12"); FileInputStream instream = new FileInputStream (file baru (jalur absolut sertifikat weChat)); coba {keystore.load (instream, "pedagang id" .tochararray ()); } akhirnya {enterstream.close (); } // mempercayai ca sendiri dan semua sertifikat yang ditandatangani sendiri sslcontext sslcontext = sslcontexts.custom (). LoadKeyMaterial (keystore, <span style = "font-family: arial, helvetica, sans-serif;"> pedagang id </span> .tochararray ()). // Izinkan TLSV1 Protocol Hanya SSLConnectionCocketFactory sslsf = SSLConnectionCockEtFactory baru (SSLContext, string baru [] {"tlsv1"}, null, sslconnectionCocketfactory.allow_all_hostname_HostName_verifier); CloseableHttpClient httpClient = httpclients.custom () .setsslsocketfactory (sslsf) .build (); // httpget httpget = baru // httpget ("https://api.mch.weixin.qq.com/secapi/pay/refund"); Httppost httppost = httppost baru ("https://api.mch.weixin.qq.com/pay/unifiedorder"); String xml = clientcustomssl.createNativePackage (noncestr, orderdescribe, orderno, price, timeStart, timeexPire); coba {stringEntity se = new stringEntity (xml); httppost.setentity (SE); System.out.println ("Execting Request" + httppost.getRequestline ()); CloseableHttpresponse responseEntry = httpclient.execute (httppost); coba {httpentity entity = responseEntry.getEntity (); System.out.println ("----------------------------------------"); System.out.println (responsEntry.getStatusLine ()); if (entitas! = null) {System.out.println ("Panjang konten respons:" + entity.getContentLength ()); /* BufferedReader bufferedReader = BufferedReader baru (inputStreamReader baru (entity.getContent ())); Teks String; while ((text = bufferedreader.readline ()))! = null) {System.out.println ("===================="+Teks); }*/ Saxreader saxreader = baru saxreader (); Dokumen dokumen = saxreader.read (entity.getContent ()); Elemen rootelt = document.getrooteLement (); System.out.println ("Node Root:" + rootelt.getName ()); System.out.println ("==="+rootelt.elementText ("result_code")); System.out.println ("==="+rootelt.elementText ("return_msg")); String resultCode = rootelt.elementText ("result_code"); JSONObject hasil = jsonObject () baru; Dokumen dokumenxml = documenthelper.parsetext (xml); Elemen rooteltxml = documentxml.getrooteLement (); if (resultCode.equals ("Success")) {System.out.println ("================== Prepay_id ====================="+ rootelt.elementText ("prepay_id"))); System.out.println ("================= Tanda ====================="+ rooteltxml.elementText ("tanda")); result.put ("weixInpayurl", rootelt.elementText ("code_url")); result.put ("prepayid", rootelt.elementText ("prepay_id")); result.put ("status", "sukses"); result.put ("msg", "success"); } else {result.put ("status", "false"); result.put ("msg", rootelt.elementText ("err_code_des")); } hasil pengembalian; } Entityutils.consume (entitas); } akhirnya {responseEntry.close (); }} akhirnya {httpclient.close (); } return null; } catch (Exception e) {E.PrintStackTrace (); JSONObject hasil = jsonObject () baru; result.put ("status", "error"); result.put ("msg", e.getMessage ()); hasil pengembalian; }}} Paket JAR HTTPCLIENT dan JSON JAR Paket: Unduh Alamat.
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.