卓越飞翔博客卓越飞翔博客

卓越飞翔 - 您值得收藏的技术分享站
技术文章11201本站已运行3223

Go语言之对接支付宝当面付程序示例


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打印到控制台上,以便进行扫码支付。

注意:在运行程序前,请根据自己的应用和配置信息更新代码中的变量值。
卓越飞翔博客
上一篇: webos私有云 更现代感的,私有云、云盘、网盘系统
下一篇: C&C++源码 QT+OPENCV实现监控
留言与评论(共有 0 条评论)
   
验证码:
隐藏边栏