ฉันได้ศึกษาการชำระเงินรหัส QR ของ Alipay เมื่อไม่นานมานี้ ฉันต้องบอกว่าเอกสาร Alipay นั้นแย่มาก (อย่างน้อยก็มาจาก Mengbi เมื่อฉันอ่านครั้งแรก) ตัวอย่างด้านบนเอกสารดูแตกต่างอย่างสิ้นเชิงจากตัวอย่างในการสาธิต บ่อยครั้งตัวอย่างด้านบนเอกสารนั้นง่ายมากในขณะที่รหัสการสาธิตนั้นซับซ้อนมากดังนั้นฉันจึงไม่รู้ว่าจะใช้รหัสใดในตอนแรก ต่อมาฉันดูรหัสในแพ็คเกจสาธิตอย่างระมัดระวังและพบว่ามีการเรียกอินเทอร์เฟซของตัวอย่างเอกสาร จากนั้นฉันก็รู้ว่าพวกเขาเป็นสิ่งเดียวกัน แต่การสาธิตจะห่ออินเตอร์เฟสของเอกสารเท่านั้น
ก่อนอื่นสมัครบัญชี Alipay ของ บริษัท บัญชีนี้มี PID และคุณต้องเพิ่มแอปพลิเคชันลงในบัญชีนี้ แต่ละแอปพลิเคชันมี AppID และคีย์สาธารณะและส่วนตัว กุญแจสาธารณะและส่วนตัวสามารถสร้างได้ผ่านเครื่องมือที่จัดทำโดย Alipay นอกจากนี้นักพัฒนา Java จำเป็นต้องใช้คีย์ส่วนตัวในรูปแบบ PKCS6 หากแอปพลิเคชันจำเป็นต้องใช้ฟังก์ชั่นการสแกนจำเป็นต้องเพิ่มตัวเลือกการชำระเงินด้วยตนเองในแอปพลิเคชันซึ่งต้องมีการลงนามในสัญญา หลังจากลงนามฟังก์ชั่นการชำระเงินด้วยตนเองแล้วจะไม่สามารถใช้งานได้โดยตรงเนื่องจากแอปพลิเคชันจะต้องออนไลน์ก่อนที่จะสามารถใช้งานได้ ดังนั้นคุณสามารถใช้แอปพลิเคชันเวอร์ชัน Sandbox ระหว่างการพัฒนา Alipay จัดเตรียมรุ่น Sandbox ของ Gateway, Alipay Public Key, PID และ APPID ซึ่งจำเป็นต้องได้รับการแก้ไขในระหว่างการกำหนดค่า
รหัสสามารถใช้รหัสในการสาธิตโดยตรงก่อนนำเข้า API ที่จัดทำโดย Alipay ในโครงการ (โปรดทราบว่าไม่ใช่รหัสสาธิต) จากนั้นนำเข้ารหัสสาธิตดังที่แสดงในรูป:
ไฟล์ com.alipay.demo.trade.main สามารถเรียกใช้ได้โดยตรง แต่ต้องกำหนดค่าไฟล์ทรัพยากร:
# ชื่อ ALIPAY GATEWAY, PANTERID และ APPID# นี่คือเกตเวย์สำหรับสภาพแวดล้อม SANDBOX OPEN_API_DOMAIN = https://openapi.alipaydev.com/gateway.domcloud_api_domain = http://mcloudmonitor.com/gateway.do AppidAppid สำหรับสภาพแวดล้อม Sandbox ของคุณด้วยตนเองที่นี่ = 2016082000300485 # RSA คีย์ส่วนตัวคีย์สาธารณะและคีย์สาธารณะ Alipay # กรุณากรอกข้อมูลในคีย์ส่วนตัวผู้ค้าของคุณที่นี่และโอนไปยังรูปแบบ pkcs8 private_key = Miiceqibadanbgkqhkig9w0baqefaascammwggjfageaaogbamkxzrfr+rnvygbs9qz2ce1mcsibreaqan+5pf5+02hyj4hzcntwqhfm91ih 3wypyhpm7xlbgj5ywjtgc4g1lz75r8a+ucyuxp8by1lv/44gi/tiflsgatfq73ocm9imxocrdyz2zcwqi1gv+b3udoy/da5w07grwizfzs6vq 1RAGMBAAECGYEAQHHC4GRBSRCKEINYTK1VHQCJ0YG11LVY85Z3SI0FNY26DVS8R5GFYDZC/MX5F8RNPUUYUHQN+4CQOR3D/C291X1ITOVITOVNEV lhejroudknp4oqriqt2w9pz8rzwzp2jcwvrvuf4ztpeimppmorp6sprfx6dlzg29sfi6gzwu6tkcqdp3mim1bhus3yonezgqc69zn0/dgofk EIX0S18QAU1X4I1FEJVTKY4HPDWIHPGYAJM0UFG1LK8MTIUNHPZRCNAKEA1QF6U1AKJM6ZSVDENRXEDTCC75UVJGSYFJWHHX9PJYD9VX8NSZV 0Z0U4V0ZG0N0YVHJ5LRO6U5FCQFRW1WIXNQJBALMCKZ8SVF/H9N6LIWMSPY6W5Q82KNRLRC7WSCENSPQT0WQL5+SACG98M0XXY5J1HMIOLHXG CTVYRIXOWOBIVQCQQCTNANB4UZ3Q/86R/KUKBVD3DIRWLFRYAHO6YXP8OY+JE/BV/359+VR3CXZYLDHZOR9/TVSPWR/Y9Q4JLEM Q1TAKEALBU7+4EDZFAP7E/FMGYKD5DML8H2IAEUMRRCPL84GHFFK/7PSQ/40NGKXPTGY44NLELHXCRPW5CZU6GQDINJOA ==#โปรด กรอกข้อมูลในการค้าของคุณ public_key ที่นี่ = MIGFMA0GCSQGSIBDQEBAQUAAA4GNADCBIQKBGQDCL2AXUFQ572IABPAS9NBNZGKIAUXMQMP/UT3+FTNH8O+B83DU01QHXZVDSB98GD8OATO Ceclibyauinzc ++ A/GVLASRST/G8TS1F+OBOV0YHY0OAE30O9ZNDPYPL6HEXWM9MQSKOTYFFM91A6MVW2UCNO4EVOSXC0ULATAWIDABAB#นี่ เป็นกุญแจสาธารณะของสภาพแวดล้อม Sandbox Alipay_Public_key = MIGFMA0GCSQGSIB3DQEBAQUAAA4GNADCBIQKBGQDIGHNON7LLILLILLKETD6BFRJ0GQGS2Y3MN1WMQMYH9ZEYWLZ5P1ZRAHRAHBXAFCFSQSHSNFSNFSNFSNFS omaqzshrvjcqjsaw1jyqrxapdkbmr90dipixmiykxv4ggakakpyj/6ftfy99uhpiq0qadd/uszqsefwo0atvp/65zi3eof7tcz32owpwidaqab# จำนวนสูงสุดของการสืบค้นและช่วงเวลาการสืบค้น (มิลลิวินาที) max_query_retry = 5Query_duration = 5000# จำนวนสูงสุดของการเลิกจ้างและช่วงเวลาการยกเลิก (MS) ในบุคคล max_cancel_retry = 3cancel_duration = 2000# การทำธุรกรรม
จากนั้นเรียกใช้ไฟล์ main.java สำหรับรหัสการชำระเงินสำหรับรหัสสแกนในแอปพลิเคชันจริงของเราเราสามารถคัดลอกฟังก์ชั่น test_trade_precreate () โดยตรงในไฟล์ main.java และสร้างฟังก์ชั่นในคอนโทรลเลอร์:
@RequestMapping (value = "/pay/alipay", method = requestMethod.post) แผนที่สาธารณะ <สตริงสตริง> ALIPAY (@RequestParam จำนวนสตริง, @RequestParam int userId) {แผนที่ <สตริง, สตริง> แผนที่ = ใหม่ hashmap <สตริง, สตริง> (); // (จำเป็น) หมายเลขคำสั่งซื้อที่ไม่ซ้ำกันในระบบการสั่งซื้อเว็บไซต์ของผู้ค้าที่มีอักขระเพียง 64 ตัวเท่านั้นสามารถมีตัวอักษรตัวเลขและขีดเส้นใต้ได้เท่านั้น // มีความจำเป็นเพื่อให้แน่ใจว่าระบบการค้าไม่สามารถทำซ้ำได้ ขอแนะนำให้สร้างผ่านลำดับฐานข้อมูล, สตริง outtradeno = "xxxxx" + system.currenttimeMillis () + (ยาว) (math.random () * 10,000000l); // (จำเป็น) ชื่อเรื่องการสั่งซื้ออธิบายวัตถุประสงค์การชำระเงินของผู้ใช้โดยประมาณ ตัวอย่างเช่น "XXX Brand XXX Store จ่ายด้วยตนเองและสแกนรหัสเพื่อใช้" String subject = "จ่าย"; // (จำเป็น) จำนวนเงินทั้งหมดของคำสั่งซื้อคือ 100 ล้านหยวนและไม่เกิน 100 ล้านหยวน // ถ้า [จำนวนเงินลดราคา], [ไม่ลดจำนวนเงิน] และ [จำนวนคำสั่งซื้อทั้งหมด] จะถูกส่งในเวลาเดียวกันเงื่อนไขต่อไปนี้จะต้องปฏิบัติตาม: [จำนวนคำสั่งซื้อทั้งหมด] = [จำนวนเงินลดราคา] + // (ไม่บังคับ) คำสั่งซื้อไม่สามารถลดจำนวนเงินได้และสามารถกำหนดค่าได้ด้วยแพลตฟอร์มการค้าเพื่อกำหนดค่ากิจกรรมส่วนลด หากแอลกอฮอล์ไม่ได้เข้าร่วมในส่วนลดจำนวนเงินที่สอดคล้องกันจะถูกกรอกในฟิลด์นี้ // หากค่าไม่ได้ส่ง แต่ [จำนวนคำสั่งซื้อทั้งหมด] และ [จำนวนเงินลดราคา] จะถูกส่งค่าเริ่มต้นค่าเริ่มต้นไปยัง [จำนวนคำสั่งซื้อทั้งหมด]-[จำนวนเงินลดราคา] สตริง undiscountableamount = "0"; // รหัสบัญชี Alipay ของผู้ขายใช้เพื่อสนับสนุนการชำระเงินไปยังบัญชีการชำระเงินที่แตกต่างกันภายใต้บัญชีสัญญา (ชำระเงินให้กับบัญชี Alipay ที่สอดคล้องกับ SellerId) // หากฟิลด์นี้ว่างเปล่ามันจะเริ่มต้นกับ PID ของผู้ค้าที่ลงนามกับ Alipay นั่นคือ PID ที่สอดคล้องกับสตริง Appid // คำอธิบายคำสั่งซื้อคุณสามารถอธิบายการทำธุรกรรมหรือผลิตภัณฑ์ในลักษณะโดยละเอียดเช่นการเติมใน "2 การซื้อ 2 รายการทั้งหมด 15.00 หยวน" ตัวสตริง = "3 การซื้อ 3 รายการทั้งหมด 20.00 หยวน"; // หมายเลขผู้ประกอบการผู้ค้าเพิ่มพารามิเตอร์นี้เพื่อทำสถิติการขายสำหรับผู้ประกอบการสตริงผู้ประกอบการผู้ประกอบการ = "test_operator_id"; // (จำเป็น) หมายเลขร้านค้าของผู้ค้าผ่านหมายเลขร้านค้าและแบ็กเอนด์ผู้ค้าคุณสามารถกำหนดค่าข้อมูลส่วนลดให้กับร้านค้าได้อย่างถูกต้อง สำหรับรายละเอียดโปรดปรึกษา Alipay Technical Support String storeId = "2088102172329883"; // พารามิเตอร์การขยายธุรกิจปัจจุบันคุณสามารถเพิ่มหมายเลขผู้ให้บริการระบบที่กำหนดโดย Alipay (ผ่านวิธี SetSySserviceProviderId) สำหรับรายละเอียดโปรดปรึกษา Alipay Technical Support ExtendParams ExtendParams = New ExtendParams (); Extendparams.setsssserviceproviderid ("2088100200300400500"); // หมดเวลาชำระเงินกำหนดเป็น 120 นาทีสตริงหมดเวลา Express = หมดเวลา; // // รายละเอียดผลิตภัณฑ์คุณต้องกรอกรายละเอียดของผลิตภัณฑ์ซื้อ // รายการ <HotesDetail> GoodsDetaillist = New ArrayList <GoodsDetail> (); // // สร้างข้อมูลผลิตภัณฑ์ หากคุณต้องการเพิ่มหมวดหมู่ผลิตภัณฑ์โปรดดูที่ GoodsDetail // GoodsDetail Goods1 = GoodsDetail.newInstance ("Goods_id001", "XXX ขนมปังขนาดเล็ก", 1000, 1); // // เพิ่มรายละเอียดผลิตภัณฑ์ ผลิตภัณฑ์ที่ผู้ใช้ซื้อคือ "แปรงสีฟันสีดำ" โดยมีราคาต่อหน่วย 5.00 หยวน ฉันซื้อสองชิ้น // goodsdetail goods2 = goodsdetail.newinstance ("goods_id002", "แปรงสีฟัน xxx", 500, 2); // goodsdetaillist.add (goods2); // สร้างรหัสสแกนเพื่อชำระค่าตัวสร้างคำขอตั้งค่าพารามิเตอร์การร้องขอ ALIPAYTRADEPRECREATEREQUESTBUILDER BUILDER = ALIPAYTRADEPRECREATEREALEQUESTBUILDER () .SetSellerID (SellerID) .SetBody (Body) .setOperatorId (operatorId) .setStoreId (storeId) .SetextendParams (ExtendParams) .SetTimeOutExpress (TimeOutExpress) เซิร์ฟเวอร์จะแจ้งเส้นทางหน้า HTTP ที่ระบุไว้ในเซิร์ฟเวอร์อย่างแข็งขัน ตั้งค่าตามต้องการ ที่นี่เราตั้งค่าอินเทอร์เฟซที่เราเขียนเอง เราจะแนะนำในภายหลัง // .SetGoodsDetaillist (GoodsDetaillist); ALIPAYF2FPRECREATERESULT RESURES = TradESERVICE.TRADEPRECREATE (BUILDER); switch (result.getTradestatus ()) {ความสำเร็จในกรณี: log.info ("ALIPAY สั่งซื้อล่วงหน้าสำเร็จ :)"); System.out.println ("ALIPAY สั่งซื้อล่วงหน้าสำเร็จ :)"); AlipayTradePrecReateresponse การตอบสนอง = result.getResponse (); // dumpresponse (การตอบสนอง); // system.out.println (response.getbody ()); // // // มันจำเป็นต้องได้รับการแก้ไขไปยังเส้นทางบนเครื่องทำงาน // String FilePath) log.info ("filepath:" + filepath); // zxingutils.getqrcodeimge (response.getqrcode (), 256, filepath); // system.out.println (response.getqrcode ()); // สร้างคำสั่งซื้อและแทรกการสั่งซื้อฐานข้อมูล baobiaoorder = ใหม่ baobiaoorder (userid, outtradeno, "", double.parsedouble (จำนวน), วันที่ใหม่ (), 1); baobiaoRorderservice.insertorder (คำสั่งซื้อ); map.put ("สถานะ", "true"); map.put ("qrcode", response.getQrCode ()); // กลับไปที่ Map.put รหัสไคลเอนต์ ("Outtradeno", Outtradeno); แผนที่กลับ; กรณีล้มเหลว: log.error ("การสั่งซื้อล่วงหน้า Alipay ล้มเหลว !!!"); System.out.println ("การสั่งซื้อล่วงหน้า Alipay ล้มเหลว !!!"); System.out.println (result.getResponse (). getBody ()); หยุดพัก; กรณีที่ไม่ทราบ: log.error ("ข้อยกเว้นระบบ, ไม่ทราบสถานะการสั่งซื้อล่วงหน้า !!!"); System.out.println ("ข้อยกเว้นระบบไม่ทราบสถานะการสั่งซื้อล่วงหน้า !!!"); หยุดพัก; ค่าเริ่มต้น: log.error ("สถานะการทำธุรกรรมที่ไม่ได้รับการสนับสนุนการทำธุรกรรมส่งคืนข้อยกเว้น !!!"); System.out.println ("สถานะการทำธุรกรรมที่ไม่ได้รับการสนับสนุนการทำธุรกรรมส่งคืนข้อยกเว้น !!!"); หยุดพัก; } map.put ("สถานะ", "false"); map.put ("msg", "ระบบมีข้อยกเว้นโปรดลองอีกครั้งในภายหลัง!"); แผนที่กลับ; -ตรรกะคือผู้ใช้จะสแกนรหัสบนโทรศัพท์มือถือของเขาเพื่อจ่าย Aliipay และหลังจาก Alipay ได้รับมันจะส่งข้อความการชำระเงินที่ประสบความสำเร็จให้เราเพื่อตั้งค่า NOTH_URL ดังที่แสดงด้านล่าง:
@RequestMapping (value = "/pay/notify", method = requestMethod.post) สตริงสาธารณะ NotifyResult (คำขอ httpservletRequest, การตอบกลับ httpservletResponse) {log.info ( แผนที่ <string, string> params = new hashmap <string, string> (); // ดึงพารามิเตอร์ทั้งหมดเพื่อตรวจสอบการแจงนับลายเซ็น <string> parameterNames = request.getParameterNames (); ในขณะที่ (parameterNames.hasmoreElements ()) {string parameterName = parameterNames.nextElement (); params.put (parameterName, request.getParameter (parameterName)); } Boolean Signverified; ลอง {signverified = alipaysignature.rsacheckv1 (params, configs.getalipaypublickey (), "UTF-8"); } catch (alipayapiexception e) {e.printstacktrace (); กลับ "ล้มเหลว"; } if (signverified) {string outtradeno = params.get ("out_trade_no"); log.info (Outtradeno + "การแจ้งเตือนการโทรกลับคำสั่งซื้อ"); // system.out.println ("ตรวจสอบลายเซ็นสำเร็จ!"); log.info ("ตรวจสอบลายเซ็นสำเร็จ!"); // ถ้า appid ในพารามิเตอร์แตกต่างจาก appid ที่กรอกข้อมูลมันเป็นข้อยกเว้นถ้า (! configs.getAppid (). เท่ากับ (params.get ("app_id")))) {log.warn ("แตกต่างจาก appid ในเวลาที่ชำระเงินนี่เป็นข้อยกเว้น กลับ "ล้มเหลว"; } // ค้นหาคำสั่งที่สอดคล้องกับหมายเลขคำสั่งซื้อในฐานข้อมูลและเปรียบเทียบจำนวนเงินกับจำนวนเงินในฐานข้อมูล หากไม่ตรงกันก็จะแจ้งข้อยกเว้นของ baobiaoorder order = baobiaoorderservice.findorderbyouttradeno (Outtradeno); if (order == null) {log.warn (outtradeno + "ตรวจสอบคำสั่งนี้โดยไม่ต้องตรวจสอบ!"); กลับ "ล้มเหลว"; } if (order.getAmount ()! = double.parsedouble (params.get ("total_amount"))) {log.warn ("แตกต่างจากจำนวนเงินในเวลาที่ชำระเงินนี่คือการแจ้งเตือนข้อยกเว้นและควรถูกละเว้น!"); กลับ "ล้มเหลว"; } if (order.getStatus () == baobiaoorder.trade_success) กลับ "ความสำเร็จ"; // หากการสั่งซื้อได้รับการชำระเรียบร้อยแล้วให้ละเว้นสถานะสตริงการแจ้งเตือนนี้ = params.get ("trade_status"); if (status.equals ("wait_buyer_pay")) {// หากสถานะกำลังรอการชำระเงินของผู้ใช้ถ้า (order.getStatus ()! } อื่นถ้า (status.equals ("trade_closed")) {// ถ้าสถานะเป็นปิดการทำงานของการทำธุรกรรมที่ไม่ได้รับค่าตอบแทนหรือการชำระเงินจะได้รับเงินคืนอย่างสมบูรณ์หาก (order.getStatus ()! } อื่นถ้า (status.equals ("trade_success") || status.equals ("trade_finished")) {// ถ้าสถานะได้รับการจ่ายสำเร็จถ้า (order.getStatus ()! = baobiaoorder.trade_success) } else {baobiaoorderservice.modifytradestatus (baobiaoorder.unknown_state, Outtradeno); } log.info (Outtradeno + "สถานะของคำสั่งซื้อได้รับการแก้ไขเป็น" + สถานะ); } else {// ถ้าลายเซ็นการตรวจสอบไม่ผ่านการส่งคืน "ล้มเหลว"; } return "ความสำเร็จ"; -นี่อาจเป็นกรณีนี้ แต่มีการแจ้งเตือนการชำระเงินที่ประสบความสำเร็จให้กับลูกค้าน้อยลงและยังมีปัญหาด้านความปลอดภัยบางอย่าง
สุดท้ายมาสรุปปัญหาที่พบในกระบวนการนี้:
1. รหัส QR ที่ส่งคืนโดย Alipay ไม่สามารถเปิดได้โดยตรงในเบราว์เซอร์ แต่ต้องใช้เพื่อแปลงรหัส QR เพื่อสร้างรหัส QR หรือคุณสามารถดูได้ผ่านเว็บไซต์ CLI.IM
2. รหัส QR ที่สร้างขึ้นโดยสภาพแวดล้อม Alipay Sandbox สามารถสแกนได้โดยใช้โทรศัพท์มือถือ Alipay รุ่น Sandbox เท่านั้น หากสแกน Aliipay เวอร์ชันปกติรหัส QR จะหมดอายุและข้อผิดพลาดอื่น ๆ จะเกิดขึ้น
3. หากคุณไม่สามารถรับการแจ้งเตือนแบบอะซิงโครนัสที่ส่งโดย Alipay หลังจากชำระเงินคุณสามารถใช้บุรุษไปรษณีย์และเครื่องมืออื่น ๆ เพื่อตรวจสอบว่า NOTEFY_URL ที่คุณกรอกสามารถเข้าถึงได้โดยใช้ IP สาธารณะหรือไม่
4. หากคุณพบปัญหาของการอนุญาต ISV ไม่เพียงพอนั่นเป็นเพราะไม่มีการลงนามในสัญญาหรือแอปพลิเคชันไม่ได้เพิ่มฟังก์ชั่นที่สอดคล้องกันและแอปพลิเคชันไม่สามารถใช้งานได้โดยไม่ต้องออนไลน์ คุณสามารถเลือกแอปพลิเคชัน Sandbox ในระหว่างการพัฒนา
5. เมื่อลงทะเบียนโทรศัพท์มือถือ Alipay รุ่น Sandbox คุณสามารถติดต่อฝ่ายบริการลูกค้าเพื่อขอบัญชี
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น