支付宝沙箱对接
- 1.1 官网
- 1.2 秘钥生成(系统默认)
- 1.3 秘钥生成(软件生成)
- 1.4 golan 安装 SDK
- 1.5 GoLand 代码
- 1.6 前端代码
1.1 官网
沙箱官网:
https://open.alipay.com/develop/sandbox/app
秘钥用具下载:
https://opendocs.alipay.com/common/02kipk?pathHash=0d20b438
1.2 秘钥生成(系统默认)
1.3 秘钥生成(软件生成)
- 点击生成密钥
- 生成成功
- 自定义密钥
****
- 复制粘贴之前生成的公钥并点击保存
- 继续点击确认
1.4 golan 安装 SDK
go get -u github.com/smartwalle/alipay/v3
1.5 GoLand 代码
- app
- utils
- abfPay.go
- utils
package utilsimport ("fmt""github.com/smartwalle/alipay/v3""net/url"
)func ZfbPay(orderID string, totalPrice string) string {appID := "9021000131612134" // 你的appIDprivateKey := "" // 你的私钥aliPublicKey := "" // 支付宝的公钥var client, err = alipay.New(appID, privateKey, false)if err != nil {panic(err)}err = client.LoadAliPayPublicKey(aliPublicKey)if err != nil {panic(err)}//var p = alipay.TradeWapPay{}var p = alipay.TradePagePay{}p.NotifyURL = "http://192.168.137.188:5173/#/pages/pay-success/pay-success" //支付宝回调p.ReturnURL = "http://192.168.137.188:5173/#/pages/pay-success/pay-success" //支付后调转页面p.Subject = "云尚校园-订单支付" //标题p.OutTradeNo = orderID //传递一个唯一单号p.TotalAmount = totalPrice //金额//p.ProductCode = "QUICK_WAP_WAY"p.ProductCode = "FAST_INSTANT_TRADE_PAY" //网页支付var url2 *url.URLurl2, err = client.TradePagePay(p)if err != nil {fmt.Println(err)}var payURL = url2.String()println(payURL)return payURL
}
- app
- dto
- Pay.go
- dto
package dtotype ShopPay struct {ByCode string `json:"byCode"`ShopID string `json:"id"`OrderTips string `json:"tips"`OrderTotalPrice string `json:"totalPrice"`OrderStatus string `json:"status"`OrderID string `json:"order_id"`
}
- app
- model
- Pay.go
- model
package modelsimport "gorm.io/gorm"//
// ShopPay
// @Description: 生成订单号
//type ShopPay struct {gorm.ModelByCode string `gorm:"type:varchar(100)"`OrderId string `gorm:"type:varchar(100); unique;not null"` // 订单IDOrderStatus string `gorm:"type:varchar(100); not null"` // 订单状态OrderTips string `gorm:"type:varchar(200); not null"` // 订单备注OrderTotalPrice string `gorm:"type:varchar(100); not null"`ShopID string `gorm:"type:varchar(100); not null"`
}
- app
- common
- databaseMySQL.go
- common
package commonimport ("github.com/spf13/viper""gorm.io/driver/mysql""gorm.io/gorm"
)var DB *gorm.DBfunc InitDB() *gorm.DB {host := viper.GetString("datasource.host")port := viper.GetString("datasource.port")database := viper.GetString("datasource.database")username := viper.GetString("datasource.username")password := viper.GetString("datasource.password")charset := viper.GetString("datasource.charset")db, err := gorm.Open(mysql.Open(username+`:`+password+`@tcp(`+host+`:`+port+`)/`+database+`?charset=`+charset+`&parseTime=true&loc=Local`),&gorm.Config{})if err != nil {panic("failed to connect database, err: " + err.Error())}db.AutoMigrate(&model.ShopPay{})DB = dbreturn db
}func GetDB() *gorm.DB {return DB
}
- app
- config
- application.yml
- config
server:port: 9999datasource:diverName: mysqlhost: 127.0.0.1port: 3306database: go-appusername: rootpassword: 123456charset: utf8
- app
- controller
- PayController.go
- controller
package controllerimport "github.com/gin-gonic/gin"type PayController interface {AddShopPay(ctx *gin.Context)OrderPay(ctx *gin.Context)
}
- app
- controller
- pay
- pay.go
- pay
- controller
package payimport ("github.com/gin-gonic/gin""go-app/common""go-app/controller""go-app/dto"model "go-app/models""go-app/response""go-app/utils""gorm.io/gorm""strconv"
)type PayFun interface {controller.PayController
}type payDB struct {DB *gorm.DB
}func PayFunction() PayFun {db := common.GetDB()db.AutoMigrate(model.User{})return payDB{DB: db}
}func (db payDB) AddShopPay(ctx *gin.Context) {getPayData := dto.ShopPay{}ctx.BindJSON(&getPayData)getPayData.OrderStatus = "2"getPayData.OrderID = strconv.FormatInt(utils.GetSnowflakeId(), 10)if getPayData.ByCode != "" {db.DB.Debug().Create(&getPayData)}response.Success(ctx, gin.H{"data": getPayData}, "success")
}
func (db payDB) OrderPay(ctx *gin.Context) {order := model.ShopPay{}id, _ := strconv.Atoi(ctx.Params.ByName("orderID"))db.DB.Debug().Where("order_id", id).First(&order)pay := utils.ZfbPay(order.OrderId, order.OrderTotalPrice)response.Success(ctx, gin.H{"data": pay}, "success")
}
- app
- router.go
package mainimport ("github.com/gin-gonic/gin"shopController "go-app/controller/shop"
)
func CollectRoute(r *gin.Engine) *gin.Engine {// 支付页面payGroup := r.Group("api/pay/")payFun := payController.PayFunction()payGroup.POST("/AddShopPay/", payFun.AddShopPay)payGroup.POST("/orderPay/:orderID", payFun.OrderPay)return r
}
- app
- main.go
package mainimport ("github.com/gin-contrib/cors""github.com/gin-gonic/gin""github.com/spf13/viper""go-app/common""os"
)func main() {InitConfig()common.InitDB()r := gin.Default()config := cors.DefaultConfig()config.AllowAllOrigins = true //允许所有域名config.AllowMethods = []string{"GET", "POST", "OPTIONS"} //允许请求的方法config.AllowHeaders = []string{"token", "tus-resumable", "upload-length", "upload-metadata", "cache-control", "x-requested-with", "*"}r.Use(cors.New(config))// 定义路由和处理函数r = CollectRoute(r)port := viper.GetString("server.port")if port != "" {panic(r.Run(":" + port))}r.Run()
}func InitConfig() {workDir, _ := os.Getwd()viper.SetConfigName("application")viper.SetConfigType("yml")viper.AddConfigPath(workDir + "/config")err := viper.ReadInConfig()if err != nil {panic(err)}
}
1.6 前端代码
<template><view><!-- 自定义导航栏 --><view class="box-bg" style="font-size: 36rpx;"><!-- <uni-nav-bar shadow left-icon="left" right-icon="cart" title="购物车" /> --><uni-nav-bar shadow fixed="true" left-icon="left" right-text="关闭" title="支付订单" statusBar="true"@clickLeft="backCommitShop" @clickRight="colsePay" /></view><!-- 支付选择模块 --><view class="pay-main"><radio-group name=""><label><view class="pay-item"><view v-for="(item,index) in payItemIamges.data" :key="index"><view class="pay-connect"><img class="pay-item-image" :src="item.imageUrl" alt=""><view class="pay-item-text"><view class="pay-item-text-top">{{item.nameFather}}</view><view class="pay-item-text-foot">{{item.name}}</view></view><label class="pay-radio"><radio :checked="isChecked" color="#F33" /><text></text></label></view></view></view></label></radio-group></view><!-- 底部去支付模块 --><view class="foot-pay"><view class="total-pay"><view class="total">合计:</view><view class="total">¥{{payMoney}}</view></view><view class="go-pay" @tap="goPay">去支付</view></view></view>
</template><script setup>import {onLoad,} from '@dcloudio/uni-app';import {reactive,ref} from "vue"import {orderPay} from "@/api/shop/pay.js"onLoad((e) => {// 获取价格payMoney.value = e.price;// 获取订单号orderID.value = e.orderID;})// 选择支付方式const isChecked = ref(false);const payItemIamges = reactive({data: [{nameFather: "微信支付",name: "推荐微信用户使用",imageUrl: "http://s1jh1gxy3.hn-bkt.clouddn.com/shopCartCommit/wPay.png"},{nameFather: "支付宝支付",name: "推荐支付宝用户使用",imageUrl: "http://s1jh1gxy3.hn-bkt.clouddn.com/shopCartCommit/zPay.png"}]})// 获取金额const payMoney = ref(0);// 订单ID const orderID = ref(0);// 去支付const goPay = () => {uni.navigateTo({url:"@/pages/pay-success/pay-success"})orderPay(orderID.value).then(res=>{//#ifdef APP-PLUS plus.runtime.openURL(res.data.data, function(res){console.log(res);})//#endif // #ifdef H5window.open(res.data.data)// #endif})}const backCommitShop = () => {uni.navigateBack({delta: 1})}const colsePay = () => {uni.navigateTo({url: "../shop-commit/shop-commit"})}
</script><style lang="less" scoped>// 底部样式.foot-pay {border-top: 2rpx solid #fcc;line-height: 100rpx;height: 100rpx;width: 100%;position: fixed;bottom: 0;left: 0;display: flex;justify-content: space-between;align-items: center;.total-pay {display: flex;flex: 1;background-color: black;color: white;padding-left: 120rpx;.total {padding: 0rpx 7rpx;}}.go-pay {padding: 0rpx 100rpx;color: white;background-color: #49BDFB;}}// 支付样式.pay-main {margin-top: 15rpx;.pay-item {.pay-connect {display: flex;justify-content: space-between;padding: 20rpx 30rpx;border-bottom: 8rpx solid #F5F5F5;.pay-item-image {width: 100rpx;height: 100rpx;}.pay-item-text {flex: 1;padding-left: 80rpx;.pay-item-text-top {font-weight: bold;}.pay-item-text-foot {color: #636263;}}.pay-radio {padding-top: 20rpx;}}}}.box-bg {background-color: #F5F5F5;padding: 0 5px 0;}::v-deep uni-text.uni-nav-bar-text.uni-ellipsis-1 {font-size: 34rpx;font-weight: bolder;}::v-deep uni-text.uni-nav-bar-right-text {font-size: 32rpx;font-weight: bolder;}pay-item-text {flex: 1;padding-left: 80rpx;.pay-item-text-top {font-weight: bold;}.pay-item-text-foot {color: #636263;}}.pay-radio {padding-top: 20rpx;}}}}.box-bg {background-color: #F5F5F5;padding: 0 5px 0;}::v-deep uni-text.uni-nav-bar-text.uni-ellipsis-1 {font-size: 34rpx;font-weight: bolder;}::v-deep uni-text.uni-nav-bar-right-text {font-size: 32rpx;font-weight: bolder;}
</style>