Skip to content

Commit

Permalink
添加对同步返回数据验签
Browse files Browse the repository at this point in the history
  • Loading branch information
smartwalle committed Jun 26, 2017
1 parent 78756fb commit 47ecebe
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 3 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,17 @@ var url, _ = client.TradeWapPay(p)
// 直接访问该 URL 就可以了
```

#### 同步返回验签

支持自动对支付宝返回的数据进行签名验证,详细信息请参考[自行实现验签](https://doc.open.alipay.com/docs/doc.htm?docType=1&articleId=106120).

如果需要开启自动验签,只需要在初始化 AliPay 对象之后给 **AliPayPublicKey** 属性设置从支付宝管理后台获取到的支付宝公钥即可,如下:

``` Golang
var client = alipay.New(appId, partnerId, publickKey, privateKey, false)
client.AliPayPublicKey = xxx // 从支付宝管理后台获取支付宝提供的公钥
```

#### 验证支付结果

有支付或者其它动作发生后,支付宝服务器会调用我们提供的 Notify URL,并向其传递会相关的信息。参考[手机网站支付结果异步通知](https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.XM5C4a&treeId=203&articleId=105286&docType=1)
Expand Down
58 changes: 58 additions & 0 deletions alipay.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,57 @@ func (this *AliPay) doRequest(method string, param AliPayParam, results interfac
return err
}

if len(this.AliPayPublicKey) > 0 {
var dataStr = string(data)

var rootNodeName = strings.Replace(param.APIName(), ".", "_", -1) + k_RESPONSE_SUFFIX

var rootIndex = strings.LastIndex(dataStr, rootNodeName)
var errorIndex = strings.LastIndex(dataStr, k_ERROR_RESPONSE)

var content string
var sign string

if rootIndex > 0 {
content, sign = parserJSONSource(dataStr, rootNodeName, rootIndex)
} else if errorIndex > 0 {
content, sign = parserJSONSource(dataStr, k_ERROR_RESPONSE, errorIndex)
} else {
return nil
}

if ok, err := verify_response_rsa2([]byte(content), sign, this.AliPayPublicKey); ok == false {
return err
}
}

err = json.Unmarshal(data, results)
if err != nil {
return err
}

return err
}

func parserJSONSource(rawData string, nodeName string, nodeIndex int) (content string, sign string) {
var dataStartIndex = nodeIndex + len(nodeName) + 2
var signIndex = strings.LastIndex(rawData, "\"" + k_SIGN_NODE_NAME + "\"")
var dataEndIndex = signIndex - 1

var indexLen = dataEndIndex - dataStartIndex
if indexLen < 0 {
return "", ""
}
content = rawData[dataStartIndex:dataEndIndex]

var signStartIndex = signIndex + len(k_SIGN_NODE_NAME) + 4
sign = rawData[signStartIndex:]
var signEndIndex = strings.LastIndex(sign, "\"}")
sign = sign[:signEndIndex]

return content, sign
}

func sign_rsa2(keys []string, param url.Values, privateKey []byte) (s string) {
if param == nil {
param = make(url.Values, 0)
Expand Down Expand Up @@ -177,3 +221,17 @@ func verify_rsa2(req *http.Request, key []byte) (ok bool, err error) {
}
return true, nil
}


func verify_response_rsa2(data []byte, sign string, key []byte) (ok bool, err error) {
signBytes, err := base64.StdEncoding.DecodeString(sign)
if err != nil {
return false, err
}

err = encoding.VerifyPKCS1v15(data, signBytes, key, crypto.SHA256)
if err != nil {
return false, err
}
return true, nil
}
10 changes: 10 additions & 0 deletions alipay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ var (
appID = "2016073100129537"
partnerID = "2088102169227503"

aliPublicKey = []byte(`-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2MhEVUp+rRRyAD9HZfiS
g8LLxRAX18XOMJE8/MNnlSSTWCCoHnM+FIU+AfB+8FE+gGIJYXJlpTIyWn4VUMte
wh/4C8uwzBWod/3ilw9Uy7lFblXDBd8En8a59AxC6c9YL1nWD7/sh1szqej31VRI
2OXQSYgvhWNGjzw2/KS1GdrWmdsVP2hOiKVy6TNtH7XnCSRfBBCQ+LgqO1tE0NHD
DswRwBLAFmIlfZ//qZ+a8FvMc//sUm+CV78pQba4nnzsmh10fzVVFIWiKw3VDsxX
PRrAtOJCwNsBwbvMuI/ictvxxjUl4nBZDw4lXt5eWWqBrnTSzogFNOk06aNmEBTU
hwIDAQAB
-----END PUBLIC KEY-----`)

publicKey = []byte(`-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv8dXxi8wNAOqBNOh8Dv5
rh0BTb5KNgk62jDaS536Z1cDqq2JmpBYkBnzJXHAXEgBwPXgX8bGruMMjZKW8P4u
Expand Down
7 changes: 7 additions & 0 deletions const.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,10 @@ const (
// https://doc.open.alipay.com/docs/doc.htm?treeId=291&articleId=105806&docType=1
K_SUCCESS_CODE = "10000"
)


const (
k_RESPONSE_SUFFIX = "_response"
k_ERROR_RESPONSE = "error_response"
k_SIGN_NODE_NAME = "sign"
)
2 changes: 1 addition & 1 deletion encoding/rsa.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func VerifyPKCS1v15(src, sig, key []byte, hash crypto.Hash) error {
var block *pem.Block
block, _ = pem.Decode(key)
if block == nil {
return errors.New("publick key error")
return errors.New("public key error")
}

var pubInterface interface{}
Expand Down
2 changes: 1 addition & 1 deletion notify_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func GetTradeNotification(req *http.Request, aliPayPublicKey []byte) (noti *Trad
noti.VoucherDetailList = req.PostFormValue("voucher_detail_list")

if len(noti.NotifyId) == 0 {
return nil, errors.New("不是有效的 Notfiy")
return nil, errors.New("不是有效的 Notify")
}

ok, err := verify_rsa2(req, aliPayPublicKey)
Expand Down
3 changes: 2 additions & 1 deletion trade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ func TestAliPay_TradeQuery(t *testing.T) {
}

testCaes := []arg{
{"1111111", nil, "query success"},
{"trade_no_20170623022111", nil, "query success"},
//TODO:add more test case
}

for _, tc := range testCaes {
req := AliPayTradeQuery{
OutTradeNo: tc.outTradeNo,
}
client.AliPayPublicKey = aliPublicKey
resp, err := client.TradeQuery(req)
if err != tc.wanted {
t.Errorf("%s input:%s wanted:%v get:%v", tc.name, tc.outTradeNo, tc.wanted, err)
Expand Down

0 comments on commit 47ecebe

Please sign in to comment.