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 } |
appId:应用ID,即支付宝开放平台用户中心的应用ID。
privateKey:商户的私钥,用于生成签名。
publicKey:支付宝的公钥,用于验证支付宝 API 返回的签名。
amount:支付金额,单位为元。
orderId:商户系统中的订单号。
subject:商品简称。
程序首先将请求参数构造为 url.Values 对象,然后计算签名并添加到参数中。随后发送POST请求到支付宝API,获取响应并解析其中的二维码URL。最后,将二维码URL打印到控制台上,以便进行扫码支付。
注意:在运行程序前,请根据自己的应用和配置信息更新代码中的变量值。