• p2p银行充值功能模块 支付宝调用


    银行充值简介

    用户要想要投标的话,那么需要往p2p平台上进行充值
    使用支付宝沙箱 调用支付宝充值接口进行测试
    用户余额页面展示用户的余额 点击充值调用跳转到银行充值页面
    输入密码,密码正确调转到支付宝支付平台 登录账号密码进行充值
    充值成功记录到银行记录表,并且返回余额页面

    支付宝

    我们项目中只支持一种支付方式,支付宝,所以采用单例模式。保证只生成一个实例。
    企业法人信息(营业执照,法人身份证)支付宝的流程是支付宝创建应用,获取到appid。
    生成公钥私钥,私钥生成放到本地,公钥去支付宝平台换取支付宝公钥,把支付宝公钥放到本地。支付宝采用的非对称加密方式。
    qps限制100,先将请求的订单号放入队列,队列具有先进先出的特性,我使用的redis list做为队列, lpush加入,写一个接口用RRange每秒获取100个请求,向支付宝发起请求,
    支付成功回调失败
    两种:RRange取出来放入新的队列(sortedSet)中,回调成功从新队列中删除,定时任务每隔1分钟从新队列中取出前一分钟的记录,调用支付宝的查询接口查询是否支付成功,根据支付结果更新订单状态回调接口中的处理
    在回调接口中一定重新验证签名,避免回调接口被拦截,输入新订单号直接成功带来的损失。由于回调中操作了多张表操作采用事务处理。
    进入到支付宝开放平台 登录获取 appid 公钥 私钥

    在这里插入图片描述

    封装

    在创建好的utils文件夹里创建alipayorder.go文件,进行封装

    package utils
    
    import (
    	"fmt"
    	alipay "github.com/smartwalle/alipay/v3"
    	"os"
    )
    
    var (
    	appID = "2021000120615296"
    
    	privateKey   = "MIIEowIBAAKCAQEAn7kWd+6GCZJ0QED03lwXYIp0dyO*****************************......"
    	aliPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnXHeUM9kx6UkSV****************....."
    )
    
    var Client *alipay.Client
    
    func Init() {
    	var err error
    	Client, err = alipay.New(appID, privateKey, false)
    
    	if err != nil {
    		fmt.Println("初始化支付宝失败, 错误信息为", err)
    		os.Exit(-1)
    	}
    	Client.LoadAliPayPublicKey(aliPublicKey)
    }
    
    
    • 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

    flask银行存管平台

    支付宝充值时调用此接口 将用户id和金额写进充值表中
    调用

    #进行取钱
    @user_blue.route('/recharge')
    def recharge():
        req = reqparse.RequestParser()
        req.add_argument("user_id")
        req.add_argument("money")
        arse = req.parse_args()
    
        print(arse)
        sql = f"insert into recharge(user_id, money) values ({arse['user_id']},{arse['money']})"
        db.update(sql)
        db.commit()
    
        return jsonify({'code': 200})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    接口

    在创建好的controller中的open_troller,go进行编写
    前端页面点击充值按钮调用充值校验数据接口 接受前端传过来的用户id和密码 密码正确调用银行充值接口
    银行充值接口返回flask银行存管平台 银行取钱路由
    接着在调用获取支付宝地址接口 通过封装的 appid 公钥私钥 获取到支付宝充值页面
    充值成功回调前端 重定向到前端网页地址 顺便调用更新用户表&充值表

    package controller
    
    import (
    	"encoding/base64"
    	"encoding/json"
    	"fmt"
    	"github.com/gin-gonic/gin"
    	"github.com/smartwalle/alipay/v3"
    	"io/ioutil"
    	"myproject/model"
    	"myproject/utils"
    	"net/http"
    	"net/url"
    	"strconv"
    	"strings"
    	"time"
    )
    
    func Open(openGrp *gin.RouterGroup) {
    	openGrp.Use().GET("/zinentiqu", zinentiqu) 
    	openGrp.Use().GET("/wenzi", Mywenzi)
    	openGrp.Use().POST("/upload", upload)
    	openGrp.Use().POST("/open", OpenBankViews)
    	openGrp.Use().POST("/getpayurl", getpayurl)// 充值校验数据 调用银行进行取钱 openUser() // 获取支付宝地址 UplaodAlipay()
    	openGrp.Use().GET("/huidiaoaly", huidiaoaly)// 回调前端  更新用户表&充值表 StatusUser()
    	openGrp.Use().GET("/get/open", getOpenId)// 查询开户表
    	openGrp.Use().GET("/get/user", getUser)// 获取用户余额
    	openGrp.Use().GET("/aass", aass)
    }
    /*
    充值==》调用银行管理平台进行添加==》
    alxhou4794@sandbox.com
    */
    // 查询开户表
    func getOpenId(c *gin.Context) {
    	id := c.Query("userid")
    	user_info := model.OpenBank{}
    	sql := "select * from open_banks where userid=?"
    	model.GetDb().Raw(sql, id).Scan(&user_info)
    	c.JSON(200, gin.H{"code": 200, "data": user_info})
    }
    
    // 获取用户余额
    func getUser(c *gin.Context) {
    	id := c.Query("userid")
    	user_info := model.User{}
    	sql := "select * from users where id=?"
    	model.GetDb().Raw(sql, id).Scan(&user_info)
    	c.JSON(200, gin.H{"code": 200, "data": user_info})
    }
    
    // 调用银行充值
    func openUser(user_id, money string) float64 {
    	var host = "http://127.0.0.1:5000/recharge"
    	var param = map[string]string{
    		"user_id": user_id,
    		"money":   money,
    	}
    
    	uri, err := url.Parse(host)
    	if err != nil {
    		fmt.Println(err)
    	}
    	query := uri.Query()
    	for k, v := range param {
    		query.Set(k, v)
    	}
    	uri.RawQuery = query.Encode()
    
    	response, err := http.Get(uri.String())
    	if err != nil {
    		fmt.Println(err)
    	}
    	result, err := ioutil.ReadAll(response.Body)
    	if err != nil {
    		fmt.Println(err)
    	}
    	fmt.Println(">>", string(result))
    	fmt.Printf("type: %T\n", result)
    
    	var v interface{}
    	_ = json.Unmarshal([]byte(string(result)), &v)
    	data := v.(map[string]interface{})
    	fmt.Println(data["code"])
    
    	return data["code"].(float64)
    
    }
    
    // 充值校验数据
    func getpayurl(c *gin.Context) {
    	data := make(map[string]interface{})
    	_ = c.ShouldBind(&data)
    
    	// 判断密码是否正确
    	user_info := &model.OpenBank{}
    	sql := "select * from open_banks where userid=?"
    	model.GetDb().Raw(sql, data["userid"]).Scan(&user_info)
    
    	if fmt.Sprint(user_info.Password) != data["password"] {
    		c.JSON(200, gin.H{"code": 400, "msg": "密码错误"})
    		return
    	}
    	// 调用银行进行取钱
    	code := openUser(fmt.Sprint(data["userid"]), fmt.Sprint(data["num"]))
    	var url_path string
    	if code == 200 {
    		fmt.Println("000000000000000")
    		// 获取支付宝地址
    		url_path = UplaodAlipay(fmt.Sprint(data["num"]), fmt.Sprint(data["userid"]))
    
    	}
    	if url_path == "" {
    		c.JSON(200, gin.H{"code": 400, "msg": "充值失败"})
    		return
    	}
    	utils.GetRedis().Setex("user", 3600, data["userid"])
    	c.JSON(200, gin.H{"code": 200, "msg": "跳转中...", "url": url_path})
    
    }
    
    // 获取支付宝地址
    func UplaodAlipay(money, userid string) string {
    	utils.Init()
    	orderId := time.Now().UnixNano()
    	var p = alipay.TradePagePay{}
    	p.NotifyURL = "http://localhost:8000/huidiaoaly" // 异步回调
    	p.ReturnURL = "http://localhost:8000/huidiaoaly" // 同步回调
    	p.Subject = "要充值"
    	p.OutTradeNo = fmt.Sprint(orderId) // 订单号
    	p.TotalAmount = money
    	p.ProductCode = "FAST_INSTANT_TRADE_PAY"
    
    	url, err := utils.Client.TradePagePay(p)
    	if err != nil {
    		return ""
    	}
    	push_url := url.Scheme + "://" + url.Host + url.Path + "?" + url.RawQuery
    	fmt.Println(">>>", url)
    
    	return push_url
    }
    
    /*
    http://localhost:8000/news/callback?
    charset = utf-8
    out_trade_no = 1313423523
    method = alipay.trade.page.pay.return
    total_amount = 10.00
    trade_no = 2022102422001493010501925475
    auth_app_id = 2021000120615296
    version = 1.0
    app_id = 2021000120615296
    sign_type = RSA2
    seller_id = 2088621959391584
    timestamp = 2022-10-24+16%3A31%3A59
    */
    //alxhou4794@sandbox.com
    //  tfdfue7174@sandbox.com
    // 回调前端
    func huidiaoaly(c *gin.Context) {
    	// 回调前端
    	c.Redirect(http.StatusMovedPermanently, "http://localhost:8080/status/")
    	alipay.AckNotification(c.Writer)
    	order, _ := utils.Client.GetTradeNotification(c.Request)
    	fmt.Println("============", order.TotalAmount)
    	// 通知已获取信息
    	fmt.Println(">>>order:>>>", c.Query("userid"))
    	if order == nil {
    		fmt.Println("==验证失败==")
    	} else {
    		fmt.Println(order)
    	}
    	// TODO 更新状态
    	res := utils.GetRedis().Get("user")
    	fmt.Println("----------", res)
    	StatusUser(fmt.Sprint(order.TotalAmount), fmt.Sprint(res))
    
    }
    
    // 更新用户表&充值表
    func StatusUser(money, userid string) int {
    	// 添加充值表
    	id, _ := strconv.ParseInt(userid, 10, 0)
    	money_float, _ := strconv.ParseFloat(money, 2000)
    	fmt.Println(money_float)
    	fmt.Printf(">>>%T\n", money_float)
    	db := model.GetDb()
    	rec_info := &model.Recharge{
    		Userid: int(id),
    		Money:  int(money_float),
    		Status: 1,
    		Type:   1,
    	}
    	db.Create(rec_info)
    	// 更新用户表
    	user_info := model.User{}
    	sql := "select * from users where id=?"
    	db.Raw(sql, id).Scan(&user_info)
    
    	num := int(user_info.Tmoney) + int(money_float)
    	db.Exec("update users set tmoney=? where id=?", num, userid)
    
    	return 1
    }
    
    func aass(c *gin.Context) {
    	v := "10.01"
    	res, _ := strconv.ParseFloat(v, 10)
    	fmt.Println(res)
    	fmt.Printf(">>>%T\n", int(res)+1)
    }
    
    • 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
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212

    请添加图片描述

  • 相关阅读:
    BGP高级特性——4字节AS号
    当下,产业园区发展面临的十大问题
    JavaScript ES6类的定义与继承
    Chinese-LLaMA-AIpaca 指令精调
    gpf_maskf分配掩码描述
    【ansible第三次作业】
    视觉SLAM ch5——相机与图像
    新技术的成熟、商业模式的完备,产业互联网的落地提供了土壤
    Power BI依据列中值的范围不同计算公式增加一列
    vue路由&nodeJS环境搭建
  • 原文地址:https://blog.csdn.net/qishaoawei/article/details/127543731