In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-26 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
This article will explain in detail how to integrate WeChat Pay with SpringBoot. The editor thinks it is very practical, so I share it for you as a reference. I hope you can get something after reading this article.
1. Preparatory work 1.1 Database tables
WeChat Pay is involved in a total of two tables:
Order form
Payment record sheet
1.2 entity class
The entity class corresponding to the database:
Order form
@ Data@ToString@EqualsAndHashCode (callSuper = false) @ Accessors (chain = true) @ TableName ("t_order") @ ApiModel (value = "Order object", description = "order") public class Order implements Serializable {private static final long serialVersionUID = 1L; @ TableId (value = "id", type = IdType.ID_WORKER_STR) private String id; @ ApiModelProperty (value = "order number") private String orderNo; @ ApiModelProperty (value = "course id") private String courseId @ ApiModelProperty (value = "course name") private String courseTitle; @ ApiModelProperty (value = "course cover") private String courseCover; @ ApiModelProperty (value = "instructor's name") private String teacherName; @ ApiModelProperty (value = "member id") private String memberId; @ ApiModelProperty (value = "member nickname") private String nickname; @ ApiModelProperty (value = "member phone") private String mobile @ ApiModelProperty (value = "order amount") private BigDecimal totalFee; @ ApiModelProperty (value = "payment type (1: Wechat 2: Alipay)") private Integer payType; @ ApiModelProperty (value = "order status (0: not paid 1: paid)") private Integer status; @ ApiModelProperty (value = "logical deletion 1 (true) deleted, 0 (false) not deleted") private Boolean isDeleted @ ApiModelProperty (value = "creation time") @ TableField (fill = FieldFill.INSERT) private Date gmtCreate; @ ApiModelProperty (value = "update time") @ TableField (fill = FieldFill.INSERT_UPDATE) private Date gmtModified;}
Payment log form
@ Data@EqualsAndHashCode (callSuper = false) @ Accessors (chain = true) @ TableName ("t_pay_log") @ ApiModel (value = "PayLog object", description = "payment log table") public class PayLog implements Serializable {private static final long serialVersionUID = 1L; @ TableId (value = "id", type = IdType.ID_WORKER_STR) private String id; @ ApiModelProperty (value = "order number") private String orderNo; @ ApiModelProperty (value = "payment completion time") private Date payTime @ ApiModelProperty (value = "payment amount (minutes)") private BigDecimal totalFee; @ ApiModelProperty (value = "transaction serial number") private String transactionId; @ ApiModelProperty (value = "transaction status") private String tradeState; @ ApiModelProperty (value = "payment type (1: Wechat 2: Alipay)") private Integer payType; @ ApiModelProperty (value = "other attributes") private String attr @ ApiModelProperty (value = "logical deletion 1 (true) deleted, 0 (false) not deleted") private Boolean isDeleted; @ ApiModelProperty (value = "creation time") @ TableField (fill = FieldFill.INSERT) private Date gmtCreate; @ ApiModelProperty (value = "update time") @ TableField (fill = FieldFill.INSERT_UPDATE) private Date gmtModified;} 1.3 Import dependency
Import the dependencies needed by WeChat Pay in the order module service_order:
Com.github.wxpay wxpay-sdk 0.0.3 com.alibaba fastjson 1.4 profile
Configure the relevant information in the configuration file application.properties:
# Service port server.port=8007# service name spring.application.name=service-order# mysql database connection spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3306/guli?serverTimezone=GMT%2B8spring.datasource.username=rootspring.datasource.password=root# returns the global time format of json spring.jackson.date-format=yyyy-MM-dd HH:mm:ssspring.jackson.time-zone=GMT+8# configuration mapper xml file path mybatis-plus.mapper- Locations=classpath:com/atguigu/eduorder/mapper/xml/*.xml#mybatis log mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl# nacos service address spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848# turns on circuit breaker mechanism # feign.hystrix.enabled=true# sets hystrix timeout Default 1000ms#hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=3000# associated official account appidwx.pay.app_id=wx74862e0dfc69954# merchant number wx.pay.partner=155895011# merchant keywx.pay.partnerkey=T6m9iK73b0kn9g5v426MKHQH7X8rKwb# callback address wx.pay.notifyurl= http://guli.shop/api/order/weixinPay/weixinNotify# Wechat provided fixed address wx.pay.wxurl= https://api.mch.weixin.qq.com/pay/unifiedorder# Wechat query status address wx.pay.queryUrl=https:// Api.mch.weixin.qq.com/pay/orderquery1.5 creates a tool class that reads information related to WeChat Pay
Create a utility class ConstantWxPayUtils that reads the information needed by WeChat Pay:
@ Controllerpublic class ConstantWxPayUtils implements InitializingBean {@ Value ("${wx.pay.app_id}") private String appID; @ Value ("${wx.pay.partner}") private String partner; @ Value ("${wx.pay.partnerkey}") private String partnerKey; @ Value ("${wx.pay.notifyurl}") private String notifyUrl; @ Value ("${wx.pay.wxurl}") private String wxUrl @ Value ("${wx.pay.queryUrl}") private String queryUrl; / / defines the public static constant public static String WX_PAY_APP_ID; public static String WX_PAY_PARTNER; public static String WX_PAY_PARTNER_KEY; public static String WX_PAY_NOTIFY_URL; public static String WX_PAY_WX_URL; public static String WX_PAY_QUERY_URL @ Override public void afterPropertiesSet () throws Exception {WX_PAY_APP_ID = appID; WX_PAY_PARTNER = partner; WX_PAY_PARTNER_KEY = partnerKey; WX_PAY_NOTIFY_URL = notifyUrl; WX_PAY_WX_URL = wxUrl; WX_PAY_QUERY_URL=queryUrl;}} 1.6 other utility classes
Tool class OrderNoUtil for randomly generating order numbers:
Public class OrderNoUtil {/ * get order number * @ return * / public static String getOrderNo () {SimpleDateFormat sdf = new SimpleDateFormat ("yyyyMMddHHmmss"); String newDate = sdf.format (newDate ()); String result = ""; Random random = new Random (); for (int I = 0; I < 3; iTunes +) {result + = random.nextInt (10) } return newDate + result;}}
HttpClient utility class:
/ * http request client * * @ author xppll * * / public class HttpClient {private String url; private Map param; private int statusCode; private String content; private String xmlParam; private boolean isHttps; public boolean isHttps () {return isHttps;} public void setHttps (boolean isHttps) {this.isHttps = isHttps;} public String getXmlParam () {return xmlParam } public void setXmlParam (String xmlParam) {this.xmlParam = xmlParam;} public HttpClient (String url, Map param) {this.url = url; this.param = param;} public HttpClient (String url) {this.url = url;} public void setParameter (Map map) {param = map } public void addParameter (String key, String value) {if (param = = null) param = new HashMap (); param.put (key, value);} public void post () throws ClientProtocolException, IOException {HttpPost http = new HttpPost (url); setEntity (http); execute (http);} public void put () throws ClientProtocolException, IOException {HttpPut http = new HttpPut (url) SetEntity (http); execute (http);} public void get () throws ClientProtocolException, IOException {if (param! = null) {StringBuilder url = new StringBuilder (this.url); boolean isFirst = true; for (String key: param.keySet ()) {if (isFirst) url.append ("?") Else url.append ("&"); url.append (key) .append ("=") .append (param.get (key));} this.url = url.toString ();} HttpGet http = new HttpGet (url); execute (http) } / * set http post,put param * / private void setEntity (HttpEntityEnclosingRequestBase http) {if (param! = null) {List nvps = new LinkedList (); for (String key: param.keySet () nvps.add (new BasicNameValuePair (key, param.get (key); / / Parameter http.setEntity (new UrlEncodedFormEntity (nvps, Consts.UTF_8)) / / set parameters} if (xmlParam! = null) {http.setEntity (new StringEntity (xmlParam, Consts.UTF_8));}} private void execute (HttpUriRequest http) throws ClientProtocolException, IOException {CloseableHttpClient httpClient = null Try {if (isHttps) {SSLContext sslContext = new SSLContextBuilder () .loadTrustMaterial (null, new TrustStrategy () {/ / Trust all public boolean isTrusted (X509Certificate [] chain) String authType) throws CertificateException {return true }}). Build (); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory (sslContext); httpClient = HttpClients.custom (). SetSSLSocketFactory (sslsf). Build ();} else {httpClient = HttpClients.createDefault () } CloseableHttpResponse response = httpClient.execute (http); try {if (response! = null) {if (response.getStatusLine ()! = null) statusCode = response.getStatusLine () .getStatusCode (); HttpEntity entity = response.getEntity () / / response content content = EntityUtils.toString (entity, Consts.UTF_8);}} finally {response.close ();}} catch (Exception e) {e.printStackTrace ();} finally {httpClient.close () }} public int getStatusCode () {return statusCode;} public String getContent () throws ParseException, IOException {return content;} 2. Generate order
It involves service_order order module, service_ucenter user module and service-edu course module.
Service_order uses Fegin to remotely invoke methods of other modules.
For more information on the use of Fegin, please see: SpringCloud-Feign remote call
2.1 remote call user module and course module
Create in the service_order order module:
@ Component@FeignClient ("service-ucenter") / / the service name called public interface UcenterClient {/ / obtains the user information according to the user id and is used to generate the order using @ PostMapping ("/ educenter/member/getUserInfoOrder/ {id}") public UcenterMemberOrder getUserInfoOrder (@ PathVariable ("id") String id) } @ Component@FeignClient ("service-edu") / / the name of the service called public interface CourseClient {/ / query the course information according to the course id @ PostMapping ("/ eduservice/coursefront/getCourseInfoOrder/ {id}") public CourseWebOrder getCourseInfoOrder (@ PathVariable ("id") String id);} 2.2 implementation of remote invocation method
Realize the getCourseInfoOrder method of querying course information according to course id in service-edu course module
Controller layer:
/ * * query course information according to course id * @ param id away id * @ return CourseWebOrder * / @ PostMapping ("getCourseInfoOrder/ {id}") public CourseWebOrder getCourseInfoOrder (@ PathVariable ("id") String id) {CourseWebVo courseInfo = courseService.getBaseCourseInfo (id); CourseWebOrder courseWebOrder = new CourseWebOrder (); BeanUtils.copyProperties (courseInfo, courseWebOrder); return courseWebOrder;}
Service layer:
/ * * according to the course id, write a sql statement to query the course information * @ param courseId course id * @ return CourseWebVo * / @ Overridepublic CourseWebVo getBaseCourseInfo (String courseId) {return baseMapper.getBaseCourseInfo (courseId);}
Mapper layer:
SELECT ec.id, EC.`title`, EC.`price`, ec.lesson_num as lessonNum, ec.cover, ec.buy_count as buyCount, ec.view_count as viewCount, ecd.description, et.id teacherId, et.`name` AS teacherName, et.intro, et.avatar, es1.id as subjectLevelOneId, es1.`title`AS subjectLevelOne, es2.id as subjectLevelTwoId Es2.`title`AS subjectLevelTwo FROM edu_course ec LEFT JOIN edu_course_description ecd ON ec.id = ecd.id LEFT JOIN edu_teacher et ON EC.`roomid` = et.`id`LEFT JOIN edu_subject es1 ON ec.`subject _ parent_ id` = es1.`id`LEFT JOIN edu_subject es2 ON ec.`subject _ id` = es2.`id`WHERE ec.id = # {courseId}
Implement the getUserInfoOrder method of obtaining user information according to user id in service_ucenter user module
Controller layer:
/ * * obtain user information according to user id, used to generate orders using * * @ param id user id * @ return UcenterMemberOrder * / @ PostMapping ("getUserInfoOrder/ {id}") public UcenterMemberOrder getUserInfoOrder (@ PathVariable ("id") String id) {UcenterMember member = memberService.getById (id); UcenterMemberOrder memberOrder = new UcenterMemberOrder (); BeanUtils.copyProperties (member, memberOrder); return memberOrder;} 2.3 generate orders based on course id and user id
Controller layer:
@ CrossOrigin@RestController@RequestMapping ("/ eduorder/order") public class OrderController {@ Autowired private OrderService orderService / * method for generating an order * * @ param courseId course id * @ param request is used to get the user id * @ return return order number * / @ PostMapping ("createOrder/ {courseId}") public R saveOrder (@ PathVariable ("courseId") String courseId, HttpServletRequest request) {/ / obtain the user id / / create an order through the JWT tool class Return order number String orderNo = orderService.createOrderById (courseId, JwtUtils.getMemberIdByJwtToken (request)) Return R.ok () .data (orderId, orderNo);}}
Service layer:
/ * * generate orders based on courseId and userId * * @ param courseId course id * @ param userId user id * @ return return order number * / @ Overridepublic String createOrderById (String courseId, String userId) {/ / obtain user information UcenterMemberOrder userInfoOrder = ucenterClient.getUserInfoOrder (userId) according to user id through remote commission transfer; / / obtain course information CourseWebOrder courseInfoOrder = courseClient.getCourseInfoOrder (courseId) according to course id through remote commission transfer Order order = new Order (); / / order number order.setOrderNo (OrderNoUtil.getOrderNo ()); order.setCourseId (courseId); order.setCourseTitle (courseInfoOrder.getTitle ()); order.setCourseCover (courseInfoOrder.getCover ()); order.setTeacherName (courseInfoOrder.getTeacherName ()); order.setTotalFee (courseInfoOrder.getPrice ()); order.setMemberId (userId); order.setMobile (userInfoOrder.getMobile ()); order.setNickname (userInfoOrder.getNickname ()) / / payment status not paid: 0 paid: 1 order.setStatus (0); / / payment type Wechat: 1 Alipay: 2 order.setPayType (1); / / Save to database baseMapper.insert (order); / / return order number return order.getOrderNo ();} 3. Query order information 3.1 controller layer
Create a getOrderInfo in OrderController to generate an order:
/ * query order information according to order id * @ param orderId order id * @ return returns order information * / @ GetMapping ("getOrderInfo/ {orderId}") public R getOrderInfo (@ PathVariable ("orderId") String orderId) {Order order=orderService.getOrderByOrderId (orderId); return R.ok () .data ("item", order) } 3.2 service layer / * query order information according to order id * * @ param orderId order id * @ return return order information * / @ Overridepublic Order getOrderByOrderId (String orderId) {LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper (); queryWrapper.eq (Order::getOrderNo, orderId); return baseMapper.selectOne (queryWrapper);} 4. Generate WeChat Pay's QR code 4.1 controller layer
Create a createNative in PayLogController to generate the payment QR code:
@ CrossOrigin@RestController@RequestMapping ("/ eduorder/paylog") public class PayLogController {@ Autowired private PayLogService payLogService / * * generate WeChat Pay QR code according to the order number * @ param orderNo order number * @ return R * / @ GetMapping ("createNative/ {orderNo}") public R createNative (@ PathVariable ("orderNo") String orderNo) {/ / return information, including the QR code address and other information Map map=payLogService.createNative (orderNo); return R.ok () .data (map) 4.2 service layer
Generating WeChat Pay's QR code can be divided into the following steps:
Query order information according to order number
Use map to set the parameters needed to generate a QR code
Send httpclient request, pass parameters in xml format, and pass in the fixed address provided by WeChat Pay
Get the result returned by sending the request
Finally return the encapsulated data
/ * * generate WeChat Pay QR code * @ param orderNo order number * @ return map * / @ Overridepublic Map createNative (String orderNo) {try {/ / 1. Query the order information Order order = orderService.getOrderByOrderId (orderNo) according to the order number; / / 2. Use map to set the parameters Map m = new HashMap (); / / the associated official account appid m.put ("appid", ConstantWxPayUtils.WX_PAY_APP_ID); / / merchant number m.put ("mch_id", ConstantWxPayUtils.WX_PAY_PARTNER); / / random string m.put ("nonce_str", WXPayUtil.generateNonceStr ()) / / course title m.put ("body", order.getCourseTitle ()); / / order number m.put ("out_trade_no", orderNo); / / Price m.put ("total_fee", order.getTotalFee (). Multiply (new BigDecimal ("100s")). LongValue () + ") / / ip address m.put ("spbill_create_ip", "127.0.0.1"); m.put ("notify_url", ConstantWxPayUtils.WX_PAY_NOTIFY_URL); m.put ("trade_type", "NATIVE"); / / 3. Send httpclient request, pass the parameter xml format, pass in the fixed address HttpClient client = new HttpClient (ConstantWxPayUtils.WX_PAY_WX_URL) provided by WeChat Pay; / / set the parameter in xml format, which requires passing the QR code parameter m and merchant key client.setXmlParam (WXPayUtil.generateSignedXml (m, ConstantWxPayUtils.WX_PAY_PARTNER_KEY)); / / does not support https by default, but sets it to true to support client.setHttps (true) / / execute the request to send client.post (); / / 4. The result returned by the sending request / / returns the xml format String xml = client.getContent (); / / converts the xml format to the map collection Map resultMap = WXPayUtil.xmlToMap (xml); / / 5. Finally, the encapsulated data Map map = new HashMap (); / / order number map.put ("out_trade_no", orderNo); / / course id map.put ("course_id", order.getCourseId ()); / / Price map.put ("total_fee", order.getTotalFee ()) / / return QR code operation status code map.put ("result_code", resultMap.get ("result_code")); / / QR code address map.put ("code_url", resultMap.get ("code_url")); return map;} catch (Exception e) {throw new GuliException (20001, "failed to generate WeChat Pay QR code");}} 5. Query order payment status 5.1 controller layer
Create a queryPayStatus in PayLogController to obtain the payment status:
/ * * obtain payment status * @ param orderNo order number * @ return R * / @ GetMapping ("queryPayStatus/ {orderNo}") public R queryPayStatus (@ PathVariable ("orderNo") String orderNo) {Map map=payLogService.queryPayStatus (orderNo); if (map==null) {return R.error (). Message ("payment error!") ;} / / if the map is not empty, get the order status if (map.get ("trade_state"). Equals ("SUCCESS") through map {/ / add records to the payment table, update the order table order status payLogService.updateOrdersStatus (map); return R.ok (). Message ("payment successful!") ;} return R.ok (). Code (25000). Message ("paying...");} 5.2 service layer
Querying the payment status of the order according to the order number is roughly divided into the following steps:
Package parameters
Send httpclient
Get the content returned by the request
/ * query the order payment status according to the order number * @ param orderNo * @ return * / @ Overridepublic Map queryPayStatus (String orderNo) {try {/ / 1. Package parameter Map m=new HashMap (); / / associated official account appid m.put ("appid", ConstantWxPayUtils.WX_PAY_APP_ID); / / merchant number m.put ("mch_id", ConstantWxPayUtils.WX_PAY_PARTNER); / / order number m.put ("out_trade_no", orderNo) / / Random string m.put ("nonce_str", WXPayUtil.generateNonceStr ()); / / 2. Send httpclient HttpClient client = new HttpClient (ConstantWxPayUtils.WX_PAY_QUERY_URL); client.setXmlParam (WXPayUtil.generateSignedXml); client.setHttps (true); client.post (); / / 3. Get the content returned by the request String xml = client.getContent (); Map resultMap=WXPayUtil.xmlToMap (xml); return resultMap;} catch (Exception e) {e.printStackTrace (); throw new GuliException (20001, "failed to query order payment status");}}
If the payment is successful, you need to add records to the payment table and update the order status of the order table:
/ * add a record to the payment table and update the order status of the order table * @ param map * / @ Overridepublic void updateOrdersStatus (Map map) {/ / get the order number String orderNo = map.get ("out_trade_no") from map; Order order = orderService.getOrderByOrderId (orderNo); / / update the order status of the order table status if (order.getStatus (). IntValue () = = 1) {return } order.setStatus (1); orderService.updateById (order); / / add records PayLog payLog=new PayLog () to payment table t_pag_log; payLog.setOrderNo (orderNo); payLog.setPayTime (new Date ()); / / payment type payLog.setPayType (1); / / payment amount payLog.setTotalFee (order.getTotalFee ()); / / payment status payLog.setTradeState (map.get ("trade_state")) / / transaction serial number payLog.setTransactionId (map.get ("transaction_id")); / / other attributes, converted to the json string payLog.setAttr (JSONObject.toJSONString (map)); baseMapper.insert (payLog) } this is the end of the article on "how to integrate WeChat Pay with SpringBoot". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, please share it for more people to see.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.