支付宝扫码支付流程
准备工作
证书准备
关于如何制作证书可以参考官网OpenSSL工具介绍.直接用工具生成可以参考这里。生成的公钥需提供给支付宝账号管理者上传到支付宝开放平台,私钥需填写到代码中供签名时使用。支付宝提供了相应的开发测试功能,你可以点击”开发者中心”–>”研发服务”–>”沙箱”.这里给你提供了相应的app key等相关信,使用沙箱做开发测试再好不过了。
新建应用
我当前的项目为”网页移动应用”类型,新建应用地址。新建应用的相关证件请自己准备。
相关接口
流程调用
- 客户端调用服务器api,生成对应的系统order并提交对应的order信息到alipay系统,设置订单付款成功回调地址。
- 服务器端根据提交的订单获取alipay返回的付款地址.
- 客户端扫描根据地址生成的二维码进行付款,付款成功以后alipay将会调用服务器端提交订单时设置的回调地址,通知服务器端付款状态
相关实现(golang)
- 包引用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15import (
"fmt"
"net/http"
"time"
"git.coding.net/ydxxm-server/models"
"git.coding.net/ydxxm-server/pkg"
"git.coding.net/ydxxm-server/pkg/constants"
"git.coding.net/ydxxm-server/pkg/domain"
"git.coding.net/ydxxm-server/services"
alipay2 "git.coding.net/ydxxm-server/thirdparty/alipay"
"git.coding.net/ydxxm-server/tool"
"git.coding.net/ydxxm-server/tool/validate"
"github.com/smartwalle/alipay"
) - 订单接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30// @Title Pay pay of alipay
// @Description Pay pay of alipay
// @Param order body domain.OrderDomain true "order"
// @Success 200 {string} pay success
// @router /pay [post]
func (a *AlipayController) Pay() {
order := &domain.OrderDomain{}
a.ErrorHandler(a.Unmarshal(order))
a.ErrorHandler(validate.ValidatorExtend(order), http.StatusBadRequest)
order.TradeNo = tool.TradeNo(time.Now())
product := &models.Product{Id: order.ProductId}
err := productService.Read(product)
a.ErrorHandler(err, http.StatusUnprocessableEntity, constants.ProductNotFound)
order.Price = product.Price
client := alipay2.NewAlipayClient()
p := alipay.AliPayTradeWapPay{}
p.NotifyURL = tool.Joint(pkg.SingleLoader.Get("domain"), "/api/alipay/notify")
p.Subject = order.Title
p.OutTradeNo = order.TradeNo
p.TotalAmount = order.Summation()
p.ProductCode = constants.PRODUCT_CODE
url, err := client.Client.TradeWapPay(p)
a.ErrorHandler(err, http.StatusUnprocessableEntity)
a.ErrorHandler(a.addOrder(order, product), http.StatusUnprocessableEntity)
a.JsonData(domain.PayInfo{URL: url.String(), TradeNo: order.TradeNo})
} - 订单提交后回调接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44// @Title Notify alipay auth notify url
// @Description Notify alipay auth notify url
// @Success 200 {string} logout success
// @router /notify [post]
func (a *AlipayController) Notify() {
tradeNo := a.GetString("trade_no")
outTradeNo := a.GetString("out_trade_no")
amount, _ := a.GetFloat("total_amount")
buyerId := a.GetString("buyer_id")
order := &models.Order{TradeNo: outTradeNo}
err := orderService.Read(order, "trade_no")
if err != nil || !order.Validate(float32(amount)) {
a.ErrorHandler(err, http.StatusUnprocessableEntity, constants.OrderInvalid)
return
}
order.PayStatus = constants.Finished
order.Status = constants.OrderPlaying
order.OutTradeNo = tradeNo
order.Account = buyerId
history := &models.WalletHistory{
Money: order.Summation(),
WalletType: constants.AliPay,
ActionType: constants.Expense,
Account: order.Account,
}
err = orderService.Update(order)
if err != nil {
// 添加操作日志
history.Description = fmt.Sprintf(constants.PayFailedInfo, order.Account, constants.Alipay, time.Now(), amount, err.Error())
walletHistoryService.Create(history)
// 退款操作
alipay2.NewAlipayClient().Client.TradeRefund(alipay.AliPayTradeRefund{TradeNo: order.TradeNo})
a.refund(order)
return
}
history.Description = fmt.Sprintf(constants.AlipayConsumeInfo, order.Account, time.Now().Format(constants.DateYMDHM), order.Summation())
walletHistoryService.Create(history)
a.JsonData(map[string]string{})
}