支付寶手機網頁支付之golang版

本文章主要是通過golang實現了支付寶手機網頁支付的簡單封裝,封裝的基本都是請求的必傳參數,如果需要其他參數,可以自己修改BizContent結構體來滿足自己的需求。


封裝的文件大體分爲4個文件:

config.go 用來放基本配置參數,現在只放了需要用的rsa用戶私鑰和阿里rsa公鑰,其中用戶私鑰本封裝文件用的pkcs8的,你也可以修改爲pkcs1的

dao.go 主要是存放了BizConten結構體,裏面只有必傳參數,可以自行修改

sign.go 主要是生成簽名字符串的,生成正確會返回一個字符串

        pay.go 主要的封裝文件,實現了post請求,通過調用pay方法會返回一個編碼後的body體(返回的是個網頁直接輸出到頁面就好),還有一個err參數,正確返回nil


大致項目結構如下:

        

config.go文件 :

        

package alipay

const (
    private_key = ``
    alipay_public_key = ``
)

dao.go 文件 :在實際操作中,我們需要對金額做一些處理,不能直接用float,這會導致有時數據不對。在此可以使用github.com/shopspring/decimal,或者直接金額一般到分直接用戶分爲單位採用整型


package alipay


type BizContent struct {
	Subject     string `json:"subject"`
	OutTradeNo  string `json:"out_trade_no"`
	TotalAmount float32    `json:"total_amount"`
	ProductCode string `json:"product_code"`
}


sign.go 文件:通過修改rsaEncrypt方法中的x509.ParsePKCS8PrivateKey(block2.Bytes),修改爲x509.ParsePKCS1PrivateKey(block2.Bytes),這樣就可以使用pkcs1的鑰匙


package alipay
import (
	"sort"
	"fmt"
	"encoding/base64"
	"encoding/pem"
	"crypto/x509"
	"crypto/rsa"
	"crypto/sha256"
	"crypto"
	"net/url"
	"crypto/rand"
)

func sign(m url.Values) string {
	//對url.values進行排序
	sign := ""
	var keys []string
	for k := range m {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	for i, k := range keys {
		if m.Get(k) != "" {
			if i==0{
				sign = k+"="+m.Get(k)
			}else {
				sign = sign + "&"+ k+"="+m.Get(k)
			}
		}
	}
	fmt.Println(sign)
	//對排序後的數據進行rsa2加密,獲得sign
	b,_ := rsaEncrypt([]byte(sign))
	fmt.Println("加密:",b)
	fmt.Println("base加密:",base64.StdEncoding.EncodeToString(b))
	return base64.StdEncoding.EncodeToString(b)
}

func rsaEncrypt(origData []byte) ([]byte, error) {
	key := private_key

	block2, _ := pem.Decode([]byte(key))//PiravteKeyData爲私鑰文件的字節數組
	if block2 == nil {
		fmt.Println("block空")
		return nil,nil
	}
	//priv即私鑰對象,block2.Bytes是私鑰的字節流
	priv, err := x509.ParsePKCS8PrivateKey(block2.Bytes)
	if err != nil {
		fmt.Println("無法還原私鑰")
		return nil,nil
	}
	p := priv.(*rsa.PrivateKey)
	h2 := sha256.New()
	h2.Write(origData)
	hashed := h2.Sum(nil)
	signature2, err := rsa.SignPKCS1v15(rand.Reader, p,
		crypto.SHA256, hashed)//簽名
	return signature2,err
}


pay.go 文件:

package alipay

import (
	"net/url"
	"time"
	"net/http"
	"fmt"
	"io/ioutil"
	"github.com/axgle/mahonia"
)

func Pay(appId string,returnUrl string,notifyUrl string,bizContent string) (s string,err error) {
	var data = url.Values{}
	//var clusterinfo = map[string]string{}
	data.Add("app_id", appId)
	data.Add("method", "alipay.trade.wap.pay")
	if returnUrl != "" {
		data.Add("return_url",returnUrl)
	}
	if notifyUrl != "" {
		data.Add("notify_url", returnUrl)
	}
	data.Add("format", "json")
	data.Add("charset", "UTF-8")
	data.Add("sign_type", "RSA2")
	data.Add("timestamp", time.Now().Format("2006-01-02 15:04:05"))
	data.Add("version", "1.0")
	data.Add("biz_content",bizContent)
	data.Add("sign", sign(data))
	resp, err := http.PostForm("https://openapi.alipay.com/gateway.do",data)
	defer resp.Body.Close()
	if err != nil {
		fmt.Println(err)
		return "",err
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
		return "",err
	}
	d := mahonia.NewDecoder("utf-8")
	return d.ConvertString(string(body)),err
}


調用方法,在你需要調用的方法中加入以下代碼即可,例如:

func ali(c echo.Context) error {

	bizContent := new(alipay.BizContent)
	bizContent.Subject = "ceshi"
	bizContent.OutTradeNo = "1111112312312312312"
	bizContent.TotalAmount = 0.01
	bizContent.ProductCode = "QUICK_WAP_WAY"
	e,err := json.Marshal(bizContent)
	if err != nil {
		return err
	}
	body,err := alipay.Pay("","","",string(e))
	if err != nil {
		return err
	}

	return c.HTML(200,body)
}








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章