package alipay import ( "context" "crypto/rsa" "crypto/x509" "encoding/json" "encoding/pem" "errors" "fmt" "github.com/go-pay/crypto/xrsa" "github.com/go-pay/gopay" "github.com/go-pay/gopay/alipay" "github.com/go-pay/xtime" "github.com/syyongx/php2go" "strings" "time" ) const ( // URL baseUrl = "https://openapi.alipay.com/gateway.do" sandboxBaseUrl = "https://openapi.alipaydev.com/gateway.do" baseUrlUtf8 = "https://openapi.alipay.com/gateway.do?charset=utf-8" sandboxBaseUrlUtf8 = "https://openapi.alipaydev.com/gateway.do?charset=utf-8" LocationShanghai = "Asia/Shanghai" PKCS1 PKCSType = 1 PKCS8 PKCSType = 2 RSA = "RSA" RSA2 = "RSA2" ) type PKCSType uint8 type UserCertifyOpenInitData struct { AlipayUserCertifyOpenInitializeResponse struct { CertifyID interface{} `json:"certify_id"` Code interface{} `json:"code"` Msg interface{} `json:"msg"` } `json:"alipay_user_certify_open_initialize_response"` } type UserCertifyOpenQueryData struct { AlipayUserCertifyOpenQueryResponse struct { Code string `json:"code"` FailReason string `json:"fail_reason"` IdentityInfo string `json:"identity_info"` MaterialInfo string `json:"material_info"` Msg string `json:"msg"` Passed interface{} `json:"passed"` } `json:"alipay_user_certify_open_query_response"` Sign string `json:"sign"` } func commClient(notiURL string, paySet *PayData) (*alipay.Client, error) { client, _ := alipay.NewClient(paySet.AlipayAppId, paySet.AlipayPrivateKey, true) client.DebugSwitch = gopay.DebugOn //配置公共参数 client.SetCharset("utf-8"). SetNotifyUrl(notiURL) client.AutoVerifySign([]byte(paySet.AlipayPublicContentRSA2)) // 传入证书内容 err := client.SetCertSnByContent([]byte(paySet.AppPublicContent), []byte(paySet.AlipayRootContent), []byte(paySet.AlipayPublicContentRSA2)) if err != nil { return nil, err } return client, nil } // UserCertifyOpenInit is 支付宝APP支身份认证初始化服务 // alipay.user.certify.open.initialize func UserCertifyOpenInit(realName, identityNum, orderID, notiURL string, paySet *PayData) (UserCertifyOpenInitData, error) { var param = UserCertifyOpenInitData{} //初始化支付宝客户端 // appID 是在支付宝申请的APPID // priKey 是支付宝私钥 // realName 是姓名 // identityNum 是身份证 // orderID 是智莺这边生成的订单id // notiURL 通知地址url // passback_params 回调通知参数 client, _ := commClient(notiURL, paySet) fmt.Println(client) merchantConfig := map[string]string{ "return_url": notiURL, } identityParam := map[string]string{ "identity_type": "CERT_INFO", "cert_type": "IDENTITY_CARD", "cert_name": realName, "cert_no": identityNum, } var bizContent = map[string]interface{}{ "biz_code": "FACE", "merchant_config": merchantConfig, "identity_param": identityParam, "outer_order_no": orderID, } //请求参数 bizContentJson, _ := json.Marshal(bizContent) bizContentStr := strings.ReplaceAll(string(bizContentJson), "\\u0026", "&") body := make(gopay.BodyMap) body.Set("biz_content", bizContentStr) err := client.PostAliPayAPISelfV2(context.Background(), body, "alipay.user.certify.open.initialize", ¶m) if err != nil { return param, err } return param, nil } // UserCertifyOpenQuery is 身份认证记录查询 // alipay.user.certify.open.query func UserCertifyOpenQuery(certifyId, notiURL string, paySet *PayData) (UserCertifyOpenQueryData, error) { var param = UserCertifyOpenQueryData{} //初始化支付宝客户端 // appID 是在支付宝申请的APPID // priKey 是支付宝私钥 // certifyId 是认证id 初始化获得 // notiURL 通知地址url // passback_params 回调通知参数 client, _ := commClient(notiURL, paySet) fmt.Println(client) var bizContent = map[string]interface{}{ "certify_id": certifyId, } //请求参数 bizContentJson, _ := json.Marshal(bizContent) bizContentStr := strings.ReplaceAll(string(bizContentJson), "\\u0026", "&") body := make(gopay.BodyMap) body.Set("biz_content", bizContentStr) //body.Set("timeout_express", "30m") err := client.PostAliPayAPISelfV2(context.Background(), body, "alipay.user.certify.open.query", ¶m) if err != nil { return param, err } return param, nil } // UserCertifyOpenCertify is 支付宝APP身份认证开始认证 // alipay.user.certify.open.initialize func UserCertifyOpenCertify(certifyId, notiURL string, paySet *PayData) (string, error) { //初始化支付宝客户端 // appID 是在支付宝申请的APPID // priKey 是支付宝私钥 // certifyId 是认证id 初始化获得 // orderID 是智莺这边生成的订单id // notiURL 通知地址url // passback_params 回调通知参数 client, _ := commClient(notiURL, paySet) fmt.Println(client) var bizContent = map[string]interface{}{ "certify_id": certifyId, } //请求参数 bizContentJson, _ := json.Marshal(bizContent) bizContentStr := strings.ReplaceAll(string(bizContentJson), "\\u0026", "&") body := make(gopay.BodyMap) body.Set("biz_content", bizContentStr) body.Set("method", "alipay.user.certify.open.certify") body = checkPublicParam(client, body) key := xrsa.FormatAlipayPrivateKey(paySet.AlipayPrivateKey) var block *pem.Block if block, _ = pem.Decode([]byte(key)); block == nil { return "", errors.New("获取失败") } pkcs8Key, err := x509.ParsePKCS8PrivateKey(block.Bytes) if err != nil { return "", errors.New("获取失败") } pk8, ok := pkcs8Key.(*rsa.PrivateKey) if !ok { return "", errors.New("获取失败") } keys := pk8 sign, err := alipay.GetRsaSign(body, body.GetString("sign_type"), keys) if err != nil { return "", fmt.Errorf("GetRsaSign Error: %v", err) } body.Set("sign", sign) var str = "https://openapi.alipay.com/gateway.do" for k, v := range body { if strings.Contains(str, "?") == false { str += "?" + k + "=" + php2go.URLEncode(v.(string)) } else { str += "&" + k + "=" + php2go.URLEncode(v.(string)) } } return str, nil } // 公共参数检查 func checkPublicParam(a *alipay.Client, bm gopay.BodyMap) gopay.BodyMap { bm.Set("format", "JSON") if bm.GetString("app_id") == "" && a.AppId != "" { bm.Set("app_id", a.AppId) } if bm.GetString("app_cert_sn") == "" && a.AppCertSN != "" { bm.Set("app_cert_sn", a.AppCertSN) } if bm.GetString("alipay_root_cert_sn") == "" && a.AliPayRootCertSN != "" { bm.Set("alipay_root_cert_sn", a.AliPayRootCertSN) } if bm.GetString("return_url") == "" && a.ReturnUrl != "" { bm.Set("return_url", a.ReturnUrl) } bm.Set("charset", "utf-8") if bm.GetString("charset") == "" && a.Charset != "" { bm.Set("charset", a.Charset) } bm.Set("sign_type", RSA2) if bm.GetString("sign_type") == "" && a.SignType != "" { bm.Set("sign_type", a.SignType) } bm.Set("timestamp", time.Now().Format(xtime.TimeLayout)) bm.Set("version", "1.0") if bm.GetString("notify_url") == "" && a.NotifyUrl != "" { bm.Set("notify_url", a.NotifyUrl) } if bm.GetString("app_auth_token") == "" && a.AppAuthToken != "" { bm.Set("app_auth_token", a.AppAuthToken) } return bm }