吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2194|回复: 6
收起左侧

[其他原创] Go语言之对接支付宝当面付程序示例

[复制链接]
PAOLO 发表于 2023-4-14 10:39
本帖最后由 PAOLO 于 2023-4-14 14:05 编辑

[Golang] 纯文本查看 复制代码
package main

import (
    "fmt"
    "net/http"
    "net/url"
    "strconv"
    "time"
)

func main() {
    // 支付宝应用ID
    appId := ""
    // 商户私钥
    privateKey := ""
    // 支付宝公钥
    publicKey := ""

    // 支付金额,单位为元
    amount := 0.01
    // 订单号
    orderId := "1234567890"
    // 商品简称
    subject := "测试商品"

    // 构造请求参数
    values := url.Values{}
    values.Set("app_id", appId)
    values.Set("method", "alipay.trade.precreate")
    values.Set("format", "JSON")
    values.Set("charset", "utf-8")
    values.Set("sign_type", "RSA2")
    values.Set("timestamp", time.Now().Format("2006-01-02 15:04:05"))
    values.Set("version", "1.0")
    bizContent := fmt.Sprintf(`{"out_trade_no":"%s","total_amount":"%.2f","subject":"%s"}`, orderId, amount, subject)
    values.Set("biz_content", bizContent)

    // 计算签名
    sign := calculateSign(values, privateKey)

    // 添加签名
    values.Set("sign", sign)

    // 发送请求
    resp, err := http.PostForm("https://openapi.alipay.com/gateway.do", values)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }

    // 解析响应
    qrCodeUrl, err := parseResponse(resp, publicKey)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }

    // 打印二维码 URL
    fmt.Println(qrCodeUrl)
}

// 计算签名
func calculateSign(values url.Values, privateKey string) string {
    signStr := getSignString(values)
    sign, err := signWithRSA2(signStr, privateKey)
    if err != nil {
        fmt.Println("Error:", err)
        return ""
    }
    return sign
}

// 解析响应
func parseResponse(resp *http.Response, publicKey string) (string, error) {
    var respMap map[string]interface{}
    err := parseJsonResp(resp, &respMap)
    if err != nil {
        return "", err
    }
    if respMap["alipay_trade_precreate_response"] == nil {
        return "", fmt.Errorf("Invalid response: %v", respMap)
    }
    if respMap["alipay_trade_precreate_response"].(map[string]interface{})["code"].(string) != "10000" {
        return "", fmt.Errorf("%s: %s", respMap["alipay_trade_precreate_response"].(map[string]interface{})["sub_msg"].(string),
            respMap["alipay_trade_precreate_response"].(map[string]interface{})["msg"].(string))
    }
    qrCodeUrl := respMap["alipay_trade_precreate_response"].(map[string]interface{})["qr_code"].(string)
    isSuccess, err := verifyRespSign(respMap["alipay_trade_precreate_response"].(map[string]interface{}), publicKey)
    if !isSuccess {
        return "", err
    }
    return qrCodeUrl, nil
}

// 构造待签名字符串
func getSignString(values url.Values) string {
    keys := make([]string, 0, len(values))
    for k := range values {
        if k == "sign" || k == "sign_type" {
            continue
        }
        keys = append(keys, k)
    }
    sortedKeys := sortKeys(keys)
    var signStr string
    for i, k := range sortedKeys {
        if i == 0 {
            signStr = k + "=" + values.Get(k)
        } else {
            signStr += "&" + k + "=" + values.Get(k)
        }
    }
    return signStr
}

// 对参数进行字典序排序
func sortKeys(keys []string) []string {
    sorted := make([]string, len(keys))
    copy(sorted, keys)
    for i := 0; i < len(sorted)-1; i++ {
        for j := i + 1; j > 0; j-- {
            if sorted[j-1] > sorted[j] {
                sorted[j], sorted[j-1] = sorted[j-1], sorted[j]
            } else {
                break
            }
        }
    }
    return sorted
}

// 使用RSA2算法签名
func signWithRSA2(signStr string, privateKey string) (string, error) {
    signer, err := NewSigner(privateKey)
    if err != nil {
        return "", err
    }
    return signer.Sign(signStr)
}

// 验证响应签名
func verifyRespSign(respMap map[string]interface{}, publicKey string) (bool, error) {
    sign := respMap["sign"].(string)
    signType := respMap["sign_type"].(string)
    delete(respMap, "sign")
    delete(respMap, "sign_type")
    signStr := getSignStringFromMap(respMap)
    verifier := NewVerifier(publicKey, signType)
    return verifier.Verify(signStr, sign)
}

// 获取待签名字符串
func getSignStringFromMap(m map[string]interface{}) string {
    keys := make([]string, 0, len(m))
    for k := range m {
        keys = append(keys, k)
    }
    sortedKeys := sortKeys(keys)
    signStr := ""
    for i, k := range sortedKeys {
        if i == 0 {
            signStr = k + "=" + fmt.Sprintf("%v", m[k])
        } else {
            signStr += "&" + k + "=" + fmt.Sprintf("%v", m[k])
        }
    }
    return signStr
}



此程序使用阿里云网关方式访问支付宝 API,生成当面付二维码。在代码中,需要提供以下几个变量的值:
  • appId:应用ID,即支付宝开放平台用户中心的应用ID。
  • privateKey:商户的私钥,用于生成签名。
  • publicKey:支付宝的公钥,用于验证支付宝 API 返回的签名。
  • amount:支付金额,单位为元。
  • orderId:商户系统中的订单号。
  • subject:商品简称。

程序首先将请求参数构造为 url.Values 对象,然后计算签名并添加到参数中。随后发送POST请求到支付宝API,获取响应并解析其中的二维码URL。最后,将二维码URL打印到控制台上,以便进行扫码支付。


注意:在运行程序前,请根据自己的应用和配置信息更新代码中的变量值。

免费评分

参与人数 3吾爱币 +7 热心值 +3 收起 理由
LYTLYT + 1 用心讨论,共获提升!
侃遍天下无二人 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
j030110 + 1 我很赞同!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

iwatermelon 发表于 2023-4-14 10:53
非常感谢,谢谢楼主
Kls673M 发表于 2023-4-14 13:15
rxxcy 发表于 2023-4-14 20:53
1107934496 发表于 2023-4-18 08:56

可以申请减免的,好多渠道可以比银行收单低
gtsing 发表于 2023-11-14 22:11
1107934496 发表于 2023-4-18 08:56
可以申请减免的,好多渠道可以比银行收单低

请问怎么减免呢?
1107934496 发表于 2023-11-15 08:11
gtsing 发表于 2023-11-14 22:11
请问怎么减免呢?

现在问我有些晚了,已经离职了。
支付宝内对商家有很多优惠,比如线下商家签约当面付后,让bd给提资料可以降到1.5
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 18:26

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表