支付宝沙箱对接(GO语言)

news2024/9/21 16:46:53

支付宝沙箱对接

  • 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

image-20231027214014588

1.2 秘钥生成(系统默认)

image-20231027214829962

1.3 秘钥生成(软件生成)


  • 点击生成密钥

image-20231027214209352

  • 生成成功

image-20231027214306694

  • 自定义密钥

image-20231027214456066****

  • 复制粘贴之前生成的公钥并点击保存

image-20231027214551413

  • 继续点击确认

image-20231027214642751

1.4 golan 安装 SDK


go get -u github.com/smartwalle/alipay/v3

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1.5 GoLand 代码


  • app
    • utils
      • abfPay.go
package utils

import (
	"fmt"
	"github.com/smartwalle/alipay/v3"
	"net/url"
)

func ZfbPay(orderID string, totalPrice string) string {
	appID := "9021000131612134" // 你的appID
	privateKey := "" // 你的私钥
	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.URL
	url2, err = client.TradePagePay(p)
	if err != nil {
		fmt.Println(err)
	}

	var payURL = url2.String()
	println(payURL)
	return payURL
}

  • app
    • dto
      • Pay.go
package dto

type 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
package models

import "gorm.io/gorm"

//
//  ShopPay
//  @Description: 生成订单号
//

type ShopPay struct {
	gorm.Model
	ByCode          string `gorm:"type:varchar(100)"`
	OrderId         string `gorm:"type:varchar(100); unique;not null"` // 订单ID
	OrderStatus     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
package common

import (
	"github.com/spf13/viper"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var DB *gorm.DB

func 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 = db
	return db
}

func GetDB() *gorm.DB {
	return DB
}

  • app
    • config
      • application.yml
server:
  port: 9999

datasource:
  diverName: mysql
  host: 127.0.0.1
  port: 3306
  database: go-app
  username: root
  password: 123456
  charset: utf8
  • app
    • controller
      • PayController.go
package controller

import "github.com/gin-gonic/gin"

type PayController interface {
	AddShopPay(ctx *gin.Context)
	OrderPay(ctx *gin.Context)
}
  • app
    • controller
      • pay
        • pay.go
package pay

import (
	"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 main

import (
	"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 main

import (
	"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 H5
			 window.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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1911420.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MSPM0G3507——超声波模块移植代码

超声波没有做单独的代码文件 直接自己创建.c.h文件&#xff0c;将这些复制粘贴即可&#xff0c;然后进行SYSCFG配置按照这些配置即可&#xff0c;有啥问题直接评论区提出&#xff0c;如果看不懂的话评论区说一下&#xff0c;再出讲解 超声波.c文件 #include "ti_msp_dl…

线程并发库复习

1.进行和线程 什么是进程&#xff1a;进程是内存分配的基本单位&#xff0c;它是程序执行时的一个实例&#xff0c;会被放到进程就绪队列&#xff0c;等进程调度器选择它&#xff0c;给它时间片&#xff0c;它才会运行。在java中启动进程&#xff0c;main&#xff0c;test&…

【无标题】维度模型:

维度模型 基本概念维度模型中设计表主要分为2大类事实表维度表 基本概念 事实 &#xff1a;行为所产生的事情&#xff08;数据&#xff09; 维度&#xff1a;分析数据的角度&#xff08;状态&#xff09; 维度模型中设计表主要分为2大类 事实表&#xff1a;用于保存行为所产生…

实战 | YOLOv8使用TensorRT加速推理教程(步骤 + 代码)

导 读 本文主要介绍如何使用TensorRT加速YOLOv8模型推理的详细步骤与演示。 YOLOv8推理加速的方法有哪些? YOLOv8模型推理加速可以通过多种技术和方法实现,下面是一些主要的策略: 1. 模型结构优化 网络剪枝:移除模型中不重要的神经元或连接,减少模型复杂度。 模型精…

【通信协议】八、CDL(Caterpillar Data Link)协议解析

1、协议简介 CDL(Caterpillar Data Link)是caterpillar的通信协议,该品牌发动机ECM与各控制单元进行通信时,采用基于RS-485的物理层规范进行开发的CDL协议进行通信; 2、物理层 信号传输方式:差分信号(通过两条线的电压差识别逻辑0或逻辑1) 通信方式:半双工通信(只允…

iPhone短信被拉黑了怎么恢复?4步快速移除黑名单

在日常使用iPhone的过程中&#xff0c;可能会因为误操作或其他原因将某些联系人拉入黑名单&#xff0c;导致无法接收他们发送的短信。那么&#xff0c;iPhone短信被拉黑了怎么恢复&#xff1f; 其实&#xff0c;只需要简单的4步操作&#xff0c;就能快速将联系人移出黑名单&am…

Windows 安装 PyCharm

PyCharm下载 PyCharm官网&#xff1a;http://www.jetbrains.com/pycharm/download/ Professional 专业的&#xff0c;Community 社区&#xff0c;这里我们点击Community下的 DOWNLOAD下载。 PyCharm 安装使用 PyCharm是一种Python IDE&#xff0c;带有一整套可以帮助用户在使…

猎人维修大师免狗版

技术文档摘要 标题&#xff1a; 多功能维修工具集合概述 摘要&#xff1a; 本文档提供了一组多功能维修工具的概述&#xff0c;这些工具旨在为专业技术人员提供便利&#xff0c;以执行设备维修和软件解锁等任务。文档列出了各个工具的主要功能和应用场景。 关键词&#xff1…

【最新版】手把手Claude 3.5 Sonnet 详细步骤注册方法!

目录 01 Claude 3.5 Sonnet 是什么 02 Claude 3.5 Sonnet 注册方法 Step1&#xff1a;注册 Wildcard Step2&#xff1a;注册Claude3.5 Step3&#xff1a;接收并输入验证 03 使用Claude 3.5 Sonnet 04 升级Claude 3 Opus 05 结语 01 Claude 3.5 Sonnet 是什么 蛰伏了三…

鸿蒙开发:Universal Keystore Kit(密钥管理服务)【签名/验签介绍及算法规格】

签名/验签介绍及算法规格 为实现数据完整性保护和防抵赖&#xff0c;可使用生成/导入的密钥&#xff0c;对数据进行签名验签操作。 支持的算法 以下为密钥签名/验签支持的规格说明。 面向OpenHarmony的厂商适配密钥管理服务规格分为必选规格和可选规格。必选规格为所有厂商…

苍穹外卖--启用和禁用员工

实现 package com.sky.controller.admin;import com.sky.constant.JwtClaimsConstant; import com.sky.dto.EmployeeDTO; import com.sky.dto.EmployeeLoginDTO; import com.sky.dto.EmployeePageQueryDTO; import com.sky.entity.Employee; import com.sky.properties.JwtPro…

赛力斯25亿收购华为“问界”商标,估值102亿!

近日赛力斯发布公告&#xff0c;拟收购华为持有的商标及知识产权&#xff0c;华为其下属企业持有的九百一十九项商标权&#xff0c;其中七百四十项商标权已获授权&#xff0c;剩余商标权正在申请中&#xff0c;尚未获得商标注册证书&#xff0c;持有的商标及知识产权无形资产评…

Skywork-MoE,1460亿MoE模型,采用MoE Upcycling技术

Skywork-MoE&#xff0c;1460亿MoE模型&#xff0c;采用MoE Upcycling技术 原创 每日发现最新LLM 机器之心SOTA模型 2024年06月04日 18:27 北京 &#x1f3c6; 基座模型 ①项目名称&#xff1a;Skywork-MoE ★Skywork-MoE是一款千亿模型&#xff0c;具有1460亿参数、16个专家…

Java-Redis-Clickhouse-Jenkins-MybatisPlus-Zookeeper-vscode-Docker-jdbc-xxljob

文章目录 Clickhouse基础实操windows docker desktop 下载clickhousespringboot项目配置clickhouse Redis谈下你对Redis的了解&#xff1f;Redis一般都有哪些使用的场景&#xff1f;Redis有哪些常见的功能&#xff1f;Redis支持的数据类型有哪些&#xff1f;Redis为什么这么快…

初识CPlusPlus

前言 也是好久没写博客了&#xff0c;那些天也没闲着&#xff0c;去练题去了。实际上练题也可以写练题的博客&#xff0c;但是觉得太简单了些&#xff0c;于是就没有继续写下去。如今又回来写博客&#xff0c;是因为有整理了新的知识C。内容不算多&#xff0c;大多数都是书本上…

评估测试用例有效性 5个方面

评估测试用例的有效性是确保软件测试活动能够达到预期目标的关键步骤&#xff0c;有助于测试团队优化测试计划&#xff0c;提高测试效率&#xff0c;减少返工&#xff0c;节省成本。如果缺乏对测试用例的有效性评估&#xff0c;可能会导致测试用例无法覆盖关键功能点&#xff0…

微服务 | Springboot整合Seata+Nacos实现分布式事务

1、分布式事务概念说明 分布式系统会把一个应用系统拆分为可独立部署的多个服务&#xff0c;因此需要服务与服务之间远程协作才能完成事务操作&#xff0c;这种分布式系统环境下由不同的服务之间通过网络远程协作完成事务称之为分布式事务&#xff0c;例如&#xff1a;用户注册…

一站式短视频矩阵开发,高效托管!

短视频矩阵系统源码SaaS解决方案提供全面的开发服务&#xff0c;包括可视化视频编辑、矩阵式内容分发托管以及集成的多功能开发支持。 短视频矩阵&#xff1a;引爆您的数字营销革命 短视频矩阵系统是一套多功能集成解决方案&#xff0c;专为提升在短视频平台上的内容创作、管理…

[C++] 由C语言过渡到C++的敲门砖

命名空间 在C/C中&#xff0c;变量、函数和后⾯要学到的类都是⼤量存在的&#xff0c;这些变量、函数和类的名称将都存在于全局作⽤域中&#xff0c;可能会导致很多冲突。使⽤命名空间的⽬的是对标识符的名称进⾏本地化&#xff0c;以避免命名冲突或名字污染 。 在同一个工程中…

【matlab】周期性信号分析

目录 信号预处理 周期性特征提取方法 频谱分析 傅里叶变换 快速傅里叶变换&#xff08;FFT&#xff09; 周期图法 Welch法 自相关分析 时频分析 基于模型的方法 时间序列分解 应用实例 提取信号的周期性特征是一个在信号处理领域广泛应用的技术&#xff0c;特别是在…