1. การเตรียม
ผู้คนนับไม่ถ้วนได้ถามเกี่ยวกับการพัฒนาแบบจำลองดังนั้นฉันจึงโพสต์ที่นี่เพื่ออ้างอิงเท่านั้น ฉันได้อธิบายความแตกต่างระหว่างโหมดหนึ่งและโหมดสองครั้งหลายครั้ง ไม่มีอะไรมากไปกว่านั้นรหัส QR ของโหมดหนึ่งสำหรับผลิตภัณฑ์และรหัส QR ของโหมดสองสำหรับการสั่งซื้อ ฉันไม่ต้องพูดถึงรายละเอียดเฉพาะอื่น ๆ คุณสามารถไปที่เอกสารอย่างเป็นทางการเพื่อดูเอกสารด้วยตัวเองจากนั้นเลือกโหมดหนึ่งหรือโหมดสองและขึ้นอยู่กับธุรกิจของคุณ
1.1. พารามิเตอร์การกำหนดค่าที่เกี่ยวข้อง
สี่สิ่งก่อนหน้านี้ App_id และ App_Secret สามารถพบได้บนแพลตฟอร์มสาธารณะในขณะที่ MCH_ID และ API_KEY พบได้บนแพลตฟอร์มการค้าโดยเฉพาะ API_KEY จะต้องตั้งค่าบนแพลตฟอร์มการค้า สิ่งนี้เกี่ยวข้องกับความถูกต้องของการตรวจสอบพารามิเตอร์ดังนั้นจึงต้องตั้งค่าอย่างถูกต้อง แบบจำลองการชำระเงินรหัส QR นั้นคล้ายกับรุ่นการชำระเงิน QR รหัส 2 ในความเป็นจริงมันใช้เฉพาะ APP_ID, MCH_ID และ API_KEY และไม่ได้ใช้สิ่งอื่นใด ที่อยู่เอกสารอย่างเป็นทางการของโหมดหนึ่งอยู่ที่นี่: https://pay.weixin.qq.com/wiki/doc/api/native.php?Chapter=6_4
1.2. แนวคิดที่เกี่ยวข้อง
ที่นี่ฉันต้องการแก้ไขแนวคิดก่อน ในระหว่างการพัฒนาโมเดลที่สองฉันพูดถึงแนวคิดเช่น "ที่อยู่การโทรกลับการชำระเงิน" ฟังก์ชั่นของมันคือหลังจากที่ลูกค้าสแกนและชำระเงินเสร็จสิ้นเซิร์ฟเวอร์ WeChat จำเป็นต้องเข้าถึงที่อยู่ที่เราให้ไว้และส่งผลการชำระเงินให้เราเพื่อให้เราสามารถตรวจสอบคำสั่งซื้อสำหรับการจัดส่ง นี่เป็นแนวคิดและชื่อที่ค่อนข้างธรรมดาสำหรับเครื่องมือการชำระเงินอื่น ๆ อย่างไรก็ตามหลังจากนั้นฉันดูเอกสารบนเว็บไซต์ทางการของ WeChat และพบว่าในการพัฒนาแบบจำลองครั้งแรกพวกเขาเรียกสิ่งนี้ว่า "URL การแจ้งเตือนแบบอะซิงโครนัส" แทนที่จะเป็น "ที่อยู่การโทรกลับการชำระเงิน" แต่โดยพื้นฐานแล้วนี่หมายถึงความหมายเดียวกัน แต่ทำไมฉันถึงพูดถึงสิ่งนี้ที่นี่? นี่เป็นเพราะในโหมดหนึ่งจริง ๆ แล้วเรียกว่า "การโทรกลับการชำระเงิน" อีกครั้งที่เรียกว่า "รหัสการชำระเงินรหัสการชำระเงินของรหัสสแกน" สิ่งนี้แตกต่างจาก "URL การแจ้งเตือนแบบอะซิงโครนัส" ด้านบน สามารถเข้าใจได้ง่ายๆว่าเป็นอินเทอร์เฟซบนเซิร์ฟเวอร์ของเราเพื่อช่วยในการสั่งซื้อ การพัฒนาโหมดหนึ่งต้องใช้ความร่วมมือของอินเทอร์เฟซทั้งสองของ "สแกนรหัส QR เพื่อจ่าย URL การโทรกลับ" และ "URL การแจ้งเตือนแบบอะซิงโครนัส" ดังนั้นทุกคนควรแยกแยะความแตกต่างที่นี่
"URL การแจ้งเตือน Async" ถูกตั้งค่าเมื่อเรียกอินเทอร์เฟซเดียวแบบครบวงจร มันสามารถตั้งค่าแบบไดนามิกตราบใดที่อินเทอร์เฟซนี้ได้รับพารามิเตอร์การตอบสนองพารามิเตอร์ตามกฎที่เกี่ยวข้อง "สแกนรหัส QR เพื่อชำระค่าโทรกลับ" ค่อนข้างคงที่ ตั้งอยู่บนแพลตฟอร์มสาธารณะ WeChat ใช้เวลาประมาณ 10 นาทีในการมีผลหลังจากตั้งค่า หลังจากเข้าสู่ระบบแพลตฟอร์มสาธารณะ WeChat ให้เลือก WeChat Pay และคุณสามารถค้นหาได้ภายใต้แท็บการกำหนดค่าการพัฒนา:
ที่นี่เราต้องตั้งค่าที่อยู่ของเซิร์ฟเวอร์ของเราเอง (และพูดที่อยู่เครือข่ายสาธารณะอีกครั้งเพื่อให้เซิร์ฟเวอร์ WeChat สามารถค้นหาคุณได้)
1.3. สภาพแวดล้อมการพัฒนา
ฉันใช้ Servlet 3.0 พื้นฐานที่สุดเป็นสภาพแวดล้อมตัวอย่างที่นี่ เกี่ยวกับการอ้างอิงของแพ็คเกจ JAR ของบุคคลที่สามเมื่อเทียบกับการพัฒนาของรุ่น 2 นอกเหนือจากการใช้ XML Operation JDOM แล้วยังมีแพ็คเกจรหัส QR ของ Google ZXING และแพ็คเกจ Log4J ดังที่แสดงในรูปด้านล่าง:
เพื่ออำนวยความสะดวกในการดีบักขอแนะนำให้คุณลดการปรับในสภาพแวดล้อมนี้ก่อนที่จะย้ายไปยังโครงการจริง
2. การพัฒนาและการต่อสู้เชิงปฏิบัติ
ก่อนเริ่มต้นฉันขอแนะนำให้คุณไปที่เอกสารอย่างเป็นทางการเพื่อดูแผนภูมิเวลา หลังจากทำความเข้าใจกับแผนภูมิเวลาการเขียนโค้ดไม่ใช่เรื่องยาก แน่นอนถ้าคุณไม่เข้าใจภาพคุณสามารถพยายามทำความเข้าใจร่วมกับรหัสต่อไปนี้ของฉัน
2.1. การสร้างรหัส QR
ก่อนอื่นมีรหัส QR เนื้อหาในรหัส QR เป็นลิงค์และแบบฟอร์มคือ:
weixin: // wxpay/bizpayurl? sign = xxxxx & appid = xxxxx & mch_id = xxxxx & product_id = xxxxx & time_stamp = xxxxx & nonce_str = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX
สำหรับรายละเอียดคุณสามารถอ้างถึงโหมดเอกสารอย่างเป็นทางการเพื่อสร้างกฎรหัส QR ต่อไปเราต้องสร้างรหัส QR สำหรับลิงค์นี้ ฉันใช้ Google ZXING ที่นี่เพื่อสร้างรหัส QR
แพ็คเกจ com.wqy; นำเข้า java.io.ioException; นำเข้า Java.io.OutputStream; นำเข้า java.util.hashmap; นำเข้า java.util.iterator; นำเข้า java.util.map; นำเข้า java.util.set; นำเข้า java.util.sortedMap; นำเข้า java.util.treemap; นำเข้า javax.servlet.servletexception; นำเข้า Javax.servlet.annotation.webservlet; นำเข้า Javax.servlet.http.httpservlet; นำเข้า javax.servlet.http.httpservletrequest; นำเข้า Javax.servlet.http.httpservletResponse; นำเข้า org.apache.log4j.logger; นำเข้า com.google.zxing.barcodeformat; นำเข้า com.google.zxing.encodehinttype; นำเข้า com.google.zxing.multiformatwriter; นำเข้า com.google.zxing.writerexception; นำเข้า com.google.zxing.client.j2se.matrixtoimagewriter; นำเข้า com.google.zxing.common.bitmatrix; นำเข้า com.google.zxing.qrcode.decoder.errorCorrectionLevel; นำเข้า com.wqy.util.paycommonutil; นำเข้า com.wqy.util.payconfigutil; /** * คลาสการใช้งาน Servlet Pay1 */@webservlet ("/pay1") ระดับสาธารณะ Pay1 ขยาย httpservlet {ส่วนตัวคงที่สุดท้าย long serialversionuid = 1l; Logger Logger แบบคงที่ส่วนตัว = logger.getLogger (pay1.class); สาธารณะคงที่ int defaultWidThandHeight = 200; / ** * @SEE httpservlet#httpservlet () */ สาธารณะ pay1 () {super (); // toDo toDo ที่สร้างขึ้นอัตโนมัติ stub}/ ** * @See httpservlet#doGet (คำขอ httpservletrequest, httpservletResponse * การตอบสนอง) */ void doget ที่ได้รับการป้องกัน = PayCommonutil.getNonce_str (); Long Time_stamp = System.currentTimeMillis () / 1000; สตริง product_id = "hd_goodsssss_10"; คีย์สตริง = payconfigutil.api_key; // key sortedMap <วัตถุ, Object> PackageParams = new Treemap <Object, Object> (); packageParams.put ("appid", payconfigutil.app_id); packageParams.put ("mch_id", payconfigutil.mch_id); packageParams.put ("time_stamp", string.valueof (time_stamp)); PackageParams.put ("nonce_str", nonce_str); PackageParams.put ("product_id", product_id); String sign = payCommonutil.Createsign ("UTF-8", packageParams, key); // md5 hash packageparams.put ("sign", sign); // สร้างพารามิเตอร์สตริง str = tourlparams (packageparams); String payurl = "weixin: // wxpay/bizpayurl?" + str; logger.info ("payurl:"+payurl); // สร้างแผนที่รหัส QR <ENCODEHINTTYPE, OBJECT> HINTS = ใหม่ HASHMAP <ENCODEHINTTYPE, OBJECT> (); // สร้างแผนที่รหัส QR <ENCODEHINTTYPE, OBJECT> (); // ระบุคำใบ้ระดับการแก้ไขข้อผิดพลาดคำแนะนำ (encodeHintType.error_Correction, ErrorCorrectionLevel.l); // ระบุรูปแบบการเข้ารหัสคำใบ้ (ENCODEHINTTYPE.CHARACTION_SET, "UTF-8"); คำแนะนำ (encodehinttype.margin, 1); ลอง {bitmatrix bitmatrix = new MultiformatWriter (). ENCODE (PayUrl, BARCODEFORMAT.QR_CODE, DefaultWidThandHeight, DefaultWidThandHeight, คำแนะนำ); outputStream out = response.getOutputStream (); matrixtoimagewriter.writeToStream (bitmatrix, "png", ออก); // เอาต์พุตรหัส QR out.flush (); out.close (); } catch (writeRexception e) {// toDo บล็อก catch block ที่สร้างขึ้นอัตโนมัติ E.PrintStackTrace (); }} Public String TourlParams (SortedMap <Object, Object> PackageParams) {// อันที่จริงคุณไม่สามารถเรียงลำดับสตริง sb = new StringBuffer (); ตั้งค่า es = packageparams.entryset (); ตัววนซ้ำมัน = es.iterator (); ในขณะที่ (it.hasnext ()) {map.entry entry = (map.entry) it.next (); String k = (string) entry.getKey (); String V = (String) entry.getValue (); if (null! = v &&! "". เท่ากับ (v)) {sb.append (k + "=" + v + "&"); }} sb.deletecharat (sb.length ()-1); // ลบสุดท้าย & return sb.toString (); } / ** * @see httpservlet#dopost (คำขอ httpservletrequest, httpservletResponse * การตอบสนอง) * / การป้องกันโมฆะ dopost (httpservletrequest คำขอ, httpservletResponse การตอบสนอง) - 2.2. สแกนอินเทอร์เฟซ URL การโทรกลับการชำระเงิน
เมื่อลูกค้าสแกนรหัสสองหลักข้างต้นด้วย WeChat เซิร์ฟเวอร์ WeChat จะเข้าถึงอินเทอร์เฟซนี้ ที่นี่เราต้องทำตามคำสั่งรวมเพื่อให้ได้ตัวระบุเซสชันการทำธุรกรรม กระบวนการหลักของการประมวลผลมีดังนี้:
1) รับพารามิเตอร์ที่ส่งโดย WeChat Server และทำการตรวจสอบลายเซ็นของพารามิเตอร์
2) ถอดพารามิเตอร์ product_id ซึ่งเป็นพารามิเตอร์เดียวที่สามารถส่งผ่านรหัส QR พารามิเตอร์อื่น ๆ สามารถป้อนได้ตามโหมดเอกสารอย่างเป็นทางการ 1.1;
3) ประมวลผลธุรกิจของคุณเองตาม product_id เช่นการคำนวณจำนวนเงินการชำระเงินการสร้างหมายเลขคำสั่งซื้อ ฯลฯ ;
4) เรียกอินเทอร์เฟซเดียวแบบรวมเพื่อรับเซสชันการทำธุรกรรม prepay_id;
4.1) เตรียมพารามิเตอร์ที่เกี่ยวข้อง (เช่น APPID, MCH_ID, จำนวนการชำระเงิน, หมายเลขคำสั่งซื้อ, คำอธิบายผลิตภัณฑ์, ฯลฯ ), โทร WeChat เพื่อรวมอินเทอร์เฟซเดียว (คล้ายกับอินเทอร์เฟซเดี่ยวแบบรวมของการเรียกโหมด 2) ให้ความสนใจกับ "URL การแจ้งเตือนแบบอะซิงโครนัสที่กล่าวถึงข้างต้น" ซึ่งเป็นอินเทอร์เฟซ URL การแจ้งเตือนแบบอะซิงโครนัสที่จะกล่าวถึงในภายหลัง สำหรับพารามิเตอร์ที่เฉพาะเจาะจงโปรดดูเอกสารอย่างเป็นทางการเพื่อรวมพารามิเตอร์คำขอเดียว
4.2) รับพารามิเตอร์ที่ส่งคืนโดยอินเทอร์เฟซเดียวแบบรวมและตรวจสอบพารามิเตอร์
4.3) นำพารามิเตอร์ prepay_id ออกมาซึ่งเป็นตัวระบุเซสชันการทำธุรกรรมซึ่งมีความสำคัญอย่างยิ่ง พารามิเตอร์อื่น ๆ สามารถอ้างถึงเอกสารอย่างเป็นทางการเพื่อส่งคืนผลลัพธ์
5) เตรียมพารามิเตอร์ที่เกี่ยวข้อง (เช่น AppID, MCH_ID, return_code, prepay_id ฯลฯ ) และตอบกลับการเรียกคืนการชำระเงินครั้งแรก (หากขั้นตอนข้างต้นไม่ถูกต้องหากการตรวจสอบการลงชื่อเข้าใช้ล้มเหลวคุณสามารถส่งคืนพารามิเตอร์ข้อผิดพลาดไปยังเซิร์ฟเวอร์ WeChat) สำหรับพารามิเตอร์เฉพาะโปรดดูที่โหมดเอกสารอย่างเป็นทางการ 1.2 พารามิเตอร์เอาต์พุต
แพ็คเกจ com.wqy; นำเข้า Java.io.BufferedOutputStream; นำเข้า java.io.bufferedreader; นำเข้า java.io.ioException; นำเข้า Java.io.InputStreamReader; นำเข้า Java.io.InputStreamReader; นำเข้า java.util.sortedMap; นำเข้า java.util.treemap; นำเข้า javax.servlet.servletexception; นำเข้า Javax.servlet.annotation.webservlet; นำเข้า Javax.servlet.http.httpservlet; นำเข้า Javax.servlet.http.httpservletRequest; นำเข้า Javax.servlet.http.httpservletResponse; นำเข้า org.apache.log4j.logger; นำเข้า com.wqy.util.httputil; นำเข้า com.wqy.util.paycommonutil; นำเข้า com.wqy.util.payconfigutil; /** * คลาสการใช้งาน Servlet Notify1 */@webservlet ("/notify1") คลาสสาธารณะ Notify1 ขยาย httpservlet {ส่วนตัวคงที่สุดท้าย serialversionuid = 1l; Logger Logger แบบคงที่ส่วนตัว = logger.getLogger (Notify1.class); / ** * @See httpservlet#httpservlet () */ public notify1 () {super (); // toDo toDo ที่สร้างขึ้นใหม่ stub stub}/ ** * @See httpservlet#doGet (คำขอ httpservletrequest, httpservletResponse * การตอบสนอง) */ void doget ที่ได้รับการป้องกัน XML inputstream inputstream; StringBuffer sb = new StringBuffer (); inputStream = request.getInputStream (); สตริง s; bufferedReader ใน = new bufferedReader (ใหม่ inputStreamReader (inputStream, "UTF-8")); ในขณะที่ ((s = in.readline ())! = null) {sb.append (s); } in.close (); inputstream.close (); SortedMap <Object, Object> PackageParams = PayCommonutil.xmlConvertTomap (sb.toString ()); logger.info (packageparams); // คีย์สตริงข้อมูลบัญชี = payconfigutil.api_key; // คีย์สตริง resxml = ""; // คำติชมไปยัง WeChat Server // การตรวจสอบลงชื่อเข้าใช้ถ้า (PayCommonutil.istenpaysign ("UTF-8", packageParams, key)) {// appid OpenId MCH_ID is_subsribe nonce_str product_id product) สตริง product_id = (สตริง) packageParams.get ("product_id"); // แยกวิเคราะห์ product_id, คำนวณราคา ฯลฯ String out_trade_no = string.valueof (System.currentTimeMillis ()); // หมายเลขสั่งซื้อสตริง order_price = "1"; // ราคาหมายเหตุ: หน่วยราคาแบ่งออกเป็นสตริงตัว = product_id; // ชื่อผลิตภัณฑ์ถูกตั้งค่าเป็นสตริง product_id attach = "xxx store"; // สตริงข้อมูลเพิ่มเติม nonce_str0 = paycommonutil.getNonce_str (); // รับสตริง IP คอมพิวเตอร์ที่เริ่มต้น spbill_create_ip = payconfigutil.create_ip; String Trade_type = "Native"; SortedMap <Object, Object> UnifiedParams = new Treemap <Object, Object> (); UnifiedParams.put ("appid", payconfigutil.app_id); // UnifiedParams.put ("MCH_ID", payconfigutil.mch_id); // UnifiedParams.put ("out_trade_no", out_trade_no); // UnifiedParams.put ("product_id", product_id); UnifiedParams.put ("ร่างกาย", ร่างกาย); // UnifiedParams.put ("แนบ", แนบ); UnifiedParams.put ("total_fee", order_price); // ต้องเป็น unifefarams.put ("nonce_str", nonce_str0); // ต้องเป็น unifefarams.put ("spbill_create_ip", spbill_create_ip); // จะต้องเป็น unifiedParams.put ("trade_type", trade_type); // จะต้องเป็น unifefarams.put ("openId", openId); UnifiedParams.put ("NOTIFY_URL", PayConfigutil.Notify_url); // asynchronous url url string sign0 = payCommonutil.createsign ("UTF-8", UnifiedParams, key); UnifiedParams.put ("Sign", Sign0); // Signature String requestxml = payCommonutil.getRequestxml (UnifiedParams); logger.info (requestxml); // unified อินเตอร์เฟสเดี่ยวสตริง rxml = httputil.postdata (payconfigutil.ufdoder_url, requestxml); // การตอบสนองเดียวแบบครบวงจร sortedMap <object, object> reparams = payCommonutil.xmlConvertTomap (RXML); logger.info (reparams); // ตรวจสอบว่า (PayCommonutil.istenPaysign ("UTF-8", reparams, key)) {// รวมพารามิเตอร์ที่ส่งคืนโดยสตริงเดียว prepay_id (สตริง) reparams.get ("prepay_id"); // การระบุเซสชันการทำธุรกรรมใช้ได้ภายใน 2 ชั่วโมงสตริง nonce_str1 = paycommonutil.getNonce_str (); SortedMap <Object, Object> Resparams = new Treemap <Object, Object> (); resparams.put ("return_code", "ความสำเร็จ"); // resparams.put ("return_msg", "ตกลง"); resparams.put ("appid", payconfigutil.app_id); // resparams.put ("mch_id", payconfigutil.mch_id); resparams.put ("nonce_str", nonce_str1); // resparams.put ("prepay_id", prepay_id); // resparams.put ("result_code", "ความสำเร็จ"); // ต้องเป็น resparams.put ("err_code_des", "ตกลง"); String Sign1 = PayCommonutil.Createsign ("UTF-8", resparams, key); Resparams.put ("Sign", Sign1); // signature resxml = payCommonutil.getRequestxml (resparams); logger.info (resxml); } else {logger.info ("ข้อผิดพลาดการตรวจสอบลายเซ็น"); resxml = "<xml>" + "<return_code> <! [cdata [ล้มเหลว]]> </return_code>" + "<return_msg> <! }} else {logger.info ("ข้อผิดพลาดการตรวจสอบลายเซ็น"); resxml = "<xml>" + "<return_code> <! [cdata [ล้มเหลว]]> </return_code>" + "<return_msg> <! } // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ out.write (resxml.getBytes ()); out.flush (); out.close (); } / ** * @see httpservlet#dopost (คำขอ httpservletrequest, httpservletResponse * การตอบสนอง) * / การป้องกันโมฆะ dopost (httpservletrequest คำขอ, httpservletResponse การตอบสนอง) -ณ จุดนี้คำสั่งซื้อ WeChat ของผู้ใช้จะแสดงจำนวนเงินที่ต้องชำระและคำอธิบายผลิตภัณฑ์จากนั้นรอให้ลูกค้าชำระเงินให้เสร็จสมบูรณ์
2.3. การแจ้งเตือนแบบอะซิงโครนัสของอินเตอร์เฟส URL
เมื่อผู้ใช้ดำเนินการชำระเงินเสร็จสิ้นบน WeChat เซิร์ฟเวอร์ WeChat จะแจ้งอินเทอร์เฟซแบบอะซิงโครนัสและส่งผลการชำระเงินขั้นสุดท้ายให้เราเพื่อให้เราสามารถตรวจสอบคำสั่งสำหรับการจัดส่งและการดำเนินการอื่น ๆ โปรดทราบว่าอินเทอร์เฟซนี้เหมือนกับการพัฒนารุ่น 2 กระบวนการทั่วไปมีดังนี้:
1) รับพารามิเตอร์ที่ส่งโดย WeChat Server และทำการตรวจสอบลายเซ็นของพารามิเตอร์
2) นำพารามิเตอร์ผลลัพธ์ _code ออกหมายเลขคำสั่งซื้อ out_trade_no จำนวนคำสั่งซื้อ total_fee และพารามิเตอร์อื่น ๆ ที่เกี่ยวข้องกับธุรกิจ พารามิเตอร์เฉพาะสามารถอ้างถึงพารามิเตอร์การแจ้งเตือนของการแจ้งเตือนทั่วไปของผลลัพธ์การชำระเงินในเอกสารอย่างเป็นทางการ
3) การประมวลผลธุรกิจเช่นการตรวจสอบหมายเลขคำสั่งซื้อและจำนวนคำสั่งซื้อการปรับเปลี่ยนสถานะคำสั่งซื้อ ฯลฯ ;
4) เตรียมพารามิเตอร์ที่เกี่ยวข้อง (return_code และ return_msg) และตอบคำถามเซิร์ฟเวอร์ WeChat
โปรดทราบว่าหาก WeChat ได้รับคำตอบของผู้ค้าที่ไม่ประสบความสำเร็จหรือหมดเวลาและ WeChat เชื่อว่าการแจ้งเตือนล้มเหลว WeChat จะเริ่มต้นการแจ้งเตือนอีกครั้งอย่างสม่ำเสมอผ่านกลยุทธ์บางอย่างเพื่อเพิ่มอัตราความสำเร็จของการแจ้งเตือนให้มากที่สุด แต่ WeChat ไม่รับประกันว่าการแจ้งเตือนจะประสบความสำเร็จในท้ายที่สุด (ความถี่การแจ้งเตือนคือ 15/15/30/1800/1800/1800/1800/1800/1800/3600 หน่วย: วินาที)
แพ็คเกจ com.wqy; นำเข้า Java.io.BufferedOutputStream; นำเข้า java.io.bufferedreader; นำเข้า java.io.ioException; นำเข้า Java.io.InputStreamReader; นำเข้า Java.io.InputStreamReader; นำเข้า java.util.sortedMap; นำเข้า javax.servlet.servletexception; นำเข้า Javax.servlet.annotation.webservlet; นำเข้า Javax.servlet.http.httpservlet; นำเข้า javax.servlet.http.httpservletrequest; นำเข้า Javax.servlet.http.httpservletResponse; นำเข้า org.apache.log4j.logger; นำเข้า com.wqy.util.paycommonutil; นำเข้า com.wqy.util.payconfigutil; /** * คลาสการใช้งาน servlet re_notify */@webservlet ("/re_notify") คลาสสาธารณะ re_notify ขยาย httpservlet {ส่วนตัวคงที่สุดท้ายสุดท้าย serialversionuid = 1l; Logger Logger แบบคงที่ส่วนตัว = logger.getLogger (re_notify.class); / ** * @See httpservlet#httpservlet () */ สาธารณะ re_notify () {super (); // toDo toDo ที่สร้างขึ้นใหม่ stub stub}/ ** * @See httpservlet#doGet (คำขอ httpservletrequest, httpservletResponse * การตอบสนอง) */ void doget ที่ได้รับการป้องกัน พารามิเตอร์ inputstream inputstream; StringBuffer sb = new StringBuffer (); inputStream = request.getInputStream (); สตริง s; bufferedReader ใน = new bufferedReader (ใหม่ inputStreamReader (inputStream, "UTF-8")); ในขณะที่ ((s = in.readline ())! = null) {sb.append (s); } in.close (); inputstream.close (); SortedMap <Object, Object> PackageParams = PayCommonutil.xmlConvertTomap (sb.toString ()); logger.info (packageparams); // คีย์สตริงข้อมูลบัญชี = payconfigutil.api_key; // คีย์สตริง resxml = ""; // ข้อเสนอแนะถึง WeChat Server // พิจารณาว่าลายเซ็นนั้นถูกต้องหรือไม่ถ้า (PayCommonutil.istenPaysign ("UTF-8", packageParams, key)) {// - - out_trade_no = (สตริง) packageParams.get ("out_trade_no"); String total_fee = (string) packageParams.get ("total_fee"); logger.info ("MCH_ID:" + MCH_ID); logger.info ("openId:" + openId); logger.info ("is_subscribe:" + is_subscribe); logger.info ("out_trade_no:" + out_trade_no); logger.info ("total_fee:" + total_fee); /////////////////////////////////// Execute your own business logic ////////////////// logger.info("Payment successful"); // แจ้ง WeChat การยืนยันแบบอะซิงโครนัสประสบความสำเร็จ ต้องเขียนมัน มิฉะนั้นพื้นหลังจะได้รับแจ้งตลอดเวลา หลังจากแปดครั้งคุณจะคิดว่าการทำธุรกรรมล้มเหลว resxml = "<xml>" + "<return_code> <! [cdata [ความสำเร็จ]]> </return_code>" + "<return_msg> <! [cdata [ตกลง]]> </return_msg>" + " } else {logger.info ("จ่ายล้มเหลวข้อความแสดงข้อผิดพลาด:" + packageParams.get ("err_code")); resxml = "<xml>" + "<return_code> <! [cdata [ล้มเหลว]]> </return_code>" + "<return_msg> <! }} else {logger.info ("ข้อผิดพลาดการตรวจสอบลายเซ็น"); resxml = "<xml>" + "<return_code> <! [cdata [ล้มเหลว]]> </return_code>" + "<return_msg> <! } // ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- BufferedOutputStream (Response.getOutputStream ()); out.write (resxml.getBytes ()); out.flush (); out.close (); } / ** * @see httpservlet#dopost (คำขอ httpservletrequest, httpservletResponse * การตอบสนอง) * / การป้องกันโมฆะ dopost (httpservletrequest คำขอ, httpservletResponse การตอบสนอง) - 3. ผลการทดสอบ
3.1. ลิงค์รหัส QR การชำระเงินที่สร้างขึ้น
3.2. พารามิเตอร์ที่ได้รับจากอินเตอร์เฟส URL การชำระเงินการชำระเงิน
3.3. เริ่มต้นพารามิเตอร์การร้องขอเดียวแบบรวม
3.4. รวมพารามิเตอร์การส่งคืนเดียว
3.5. พารามิเตอร์การตอบกลับขั้นสุดท้ายของอินเตอร์เฟส URL การชำระเงินการชำระเงิน
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น