We use a series to explain the complete practice of microservices from requirements to online, from code to k8s deployment, from logging to monitoring, etc.
The whole project uses the microservices developed by go-zero, which basically includes go-zero and some middleware developed by related go-zero authors. The technology stack used is basically the self-developed components of the go-zero project team, basically go -zero the whole family bucket.
Actual project address: https://github.com/Mikaelemmmm/go-zero-looklook
1. Payment service business structure diagram
2. Dependencies
payment-api (payment api)
- order-rpc (order-rpc)
- payment-rpc
- usercenter (user rpc)
payment-rpc
- mqueue-rpc (message queue)
order-rpc (order-rpc)
- mqueue-rpc (message queue)
- travel-rpc
usercenter (user rpc)
- identity-rpc (authorization authentication rpc)
3. WeChat payment example
3.1 Create payment preprocessing order
1. After the user has created an order on our side, go to WeChat to create a prepaid order
app/payment/cmd/api/desc/payment.api
// 支付服务v1版本的接口
@server(
prefix: payment/v1
group: thirdPayment
)
service payment {
@doc "第三方支付:微信支付"
@handler thirdPaymentwxPay
post /thirdPayment/thirdPaymentWxPay (ThirdPaymentWxPayReq) returns (ThirdPaymentWxPayResp)
...
}
app/payment/cmd/api/internal/logic/thirdPayment/thirdPaymentwxPayLogic.go
- ThirdPaymentwxPay
See the picture below. We did a package when we created a WeChat prepayment order, because the follow-up payment business on our platform will definitely not only pay for homestay orders, but there will definitely be others. For example, we can launch a mall and courses in the future, so we use it here. Switch has made a business classification. At present, we only have homestay orders, but except for the query business, everything else is the same. We encapsulate the same logic, so we continue to look at the encapsulated method createWxPrePayOrder
app/payment/cmd/api/internal/logic/thirdPayment/thirdPaymentwxPayLogic.go
- createWxPrePayOrder
Here is to get the user's login userId to change the openid (this is where we registered and logged in before and there was a small program to register and log in, and then we obtained the openid), and then call CreatePayment in paymentRpc to create our local payment flow order number, and then pass Call WeChat sdk-> svc.NewWxPayClientV3 (here I packaged it once based on go-zero, it can be understood without any difficulty),
Then a prepaid order associated with our local flow order number is created on the WeChat side and returned to the front end, and the front end can initiate a request through js
3.2 WeChat payment callback
When the front-end takes the WeChat preprocessing order we gave to initiate payment, and the user enters the password to pay successfully, the WeChat server will call back to our server, and the callback address is filled in in our configuration.
For this callback address, we must fill in the callback processing method in our payment api service, which is the interface as shown in the figure below, so that we can receive WeChat callbacks and we can do follow-up processing.
After WeChat calls back, we need to process the callback logic, we need to call verifyAndUpdateState to change our serial number to paid
Let's take a look at the verifyAndUpdateState method. We need to check whether the order number exists, and compare the amount returned from the callback with the amount at the time of creation to update the order number. There is no need to verify the signature here, the sdk in the previous step has been processed
Here, we also need to write a rotation training interface for the front-end. After the front-end user pays successfully, the front-end cannot rely on the result returned by the front-end WeChat. It is necessary to use the interface provided by the back-end for rotation training to determine whether the flow order is really the back-end returning the payment success status. The return of this interface is successful, and the return from the WeChat front-end cannot be used as a basis, because the return of the WeChat front-end is not safe, and general developers understand Baidu that they do not know.
3.3 After payment is successful, the mini-program template message is sent
After our payment callback is successful, we will send a login code to the user, and go to the merchant to display the code. The merchant checks the code in the background, which is actually what Meituan looks like. We go to Meituan to place an order, and Meituan will give you a code. , the user takes this code to check in or consume.
ok, the callback is successful, we will call pyamentRpc to modify the current flow order status successfully
Let's see what is done in paymentRpc,
The front is verification. The core does two things. The first is to update the status. The second is to send a message to the message queue. Let’s look at the corresponding code in the message queue.
It can be seen that we used go-queue to send a kq message to kafka instead of asynq delayed message, because we want all businesses subscribed to the payment status to receive this message and do corresponding processing, although we are currently There is only one place to monitor for processing (send a small program template message to notify the user that the payment is successful), so here is a message related to the payment flow to kafka, which is the same as the previous order, just adding a message to the queue, no processing, Then let's see how it is handled in order-mq.
The previous section of order has introduced the operation mechanism of the entire order-mq. I won't say more here. We only talk about kq here.
When order-mq is started, go-queue will listen for messages in kafka
Let's take a look at the specific implementation. When the previous payment callback is successfully added to kafka, kafka in order-mq will receive the message, that is, PaymentUpdateStatusMq.Consume will receive the message of kafka, and then deserialize the data and pass it to execService for execution. Business, what is executed in execService?
You can see in the red box below, one is to modify the order status (non-payment status, the order also has its own status), the other is to send a message (SMS, WeChat applet template message) to the user
app/order/cmd/mq/internal/mqs/kq/paymentUpdateStatus.go
We will not look at modifying the order status. We can take a look at the message sent to the applet template. The LiveStateDate\LiveEndDate below was debugged and written to death. This is directly changed to the time passed by the method. Just convert it.
[Note] If the user wants to receive the Mini Program template message, he must authorize the user at the front end. This is necessary for the Mini Program and is not under our control.
To send a message here, we are not really calling WeChat sdk to send a message, but also inserting a template message into the message queue MqueueRpc (in fact, it can also be sent directly here), and then the message message service is taken from kafka and actually sent, it is to think of all Messages such as SMS, email, and WeChat are sent out from this service in a unified manner. You can flexibly design this according to your company's business or structure. It doesn't have to be this way.
So let's go straight to the message service code when we're here.
There is only one mq in the message business, because it does not need rpc and api, but only needs to send messages from the queue regularly, so its operation logic is the same as order-mq, and it is also applicable to serviceGroup management
We won't go into details, the operation logic can be seen in the order-mq section of the order service section, we only look at the specific implementation logic, go-queue fetches each WeChat applet template message data to be sent from the kafka queue , and then deserialize it to execService for processing, let's take a look at execService
execService is mainly to integrate data. It can be sent to the applet through the client of the applet sdk. Here is a note. The applet can distinguish the environment, whether it is sent to the online applet or the experience version applet, in the red box below There is a distinction inside. In fact, this is not safe. In this way, it is best to get it in the configuration file. In case someone messes up the development environment and changes it to formal, it will happen if you send openid to others. You can change this yourself.
4. Summary
Basically, the overall project service logic is almost finished here, and the collection of logs, monitoring, deployment, etc. will be introduced later.
project address
https://github.com/zeromicro/go-zero
Welcome go-zero
and star support us!
WeChat exchange group
Follow the official account of " Microservice Practice " and click on the exchange group to get the QR code of the community group.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。