umf_pay_service_ruby 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0dfd3a56983fb90cd939c31d776f7022ecbf36e0
4
+ data.tar.gz: ac3bbd718722afa2ef3f4330757046eeda7bcb2e
5
+ SHA512:
6
+ metadata.gz: af2b8aa9300f0033ac43fe50dca28288b9703529c342abee9a5b631268bf26bf56e04e34d8f1923350f4c67284057332f68ef215fe597338ff3294bb003b554d
7
+ data.tar.gz: 4be492eb04c6cb41de520c363034f21787393e3819d55f46f704cd60a8dc28054c32d65b4e8db59695a4f427942c818ebc092088539f2c0be2eaaf67ddcbb4f9
@@ -0,0 +1,101 @@
1
+ # UmfCheckReqDataAndEncrypt
2
+ # author : zhaoyingxin
3
+
4
+
5
+ require 'cgi'
6
+
7
+ require 'UmfLogger'
8
+ require 'UmfRegexUtil'
9
+ require 'UmfRSACryptUtil'
10
+
11
+
12
+ class UmfCheckReqDataAndEncrypt
13
+
14
+ # 参数校验
15
+ # service对应必填字段校验 & 正则校验
16
+ def doCheck(params)
17
+ service = params["service"]
18
+ serviceRuleMap = ServiceRule
19
+ # service对应的必填字段校验
20
+ paramStr = serviceRuleMap[service]
21
+ # 该service对应的必传字段数组
22
+ if paramStr!=nil && paramStr.length>0
23
+ arr = paramStr.split(',')
24
+ arr.each{ |elem|
25
+ if params[elem] == "" || params[elem] == nil
26
+ UmfLogger.logInfoMsg("[UMF SDK]请求接口 service = " + service + " 的参数值 "+ elem + " 不能为空")
27
+ UmfLogger.logInfoMsg("--------------------log end---------------------")
28
+ exit
29
+ end
30
+ }
31
+ # 历史订单查询接口mer_order_info_query
32
+ # trade_no和order_id这两个字段必填字段传一个即可
33
+ if service=="mer_order_info_query"
34
+ order_id = params["order_id"]
35
+ trade_no = params["trade_no"]
36
+ if (""==order_id||nil==order_id) && (""==trade_no||nil==trade_no)
37
+ UmfLogger.logInfoMsg("[UMF SDK]请求接口 service = " + service + " 的参数值 " + "order_id 和 trade_no" + " 不能同时为空")
38
+ UmfLogger.logInfoMsg("--------------------log end---------------------")
39
+ exit
40
+ end
41
+ end
42
+ end
43
+ # 该service对应的字段正则校验
44
+ ruleMap = ReqRule
45
+ ruleMapKeys = ruleMap.keys
46
+ mapKeys = params.keys
47
+ mapKeys.each{ |elem|
48
+ value = params[elem]
49
+ if !(ruleMapKeys.include?(elem))
50
+ next
51
+ elsif ruleMapKeys.include?(elem)
52
+ regex = ruleMap[elem]
53
+ if value!="" && value!=nil && regex!="" && regex!=nil
54
+ #TODO 存在正则校验不通过的情况
55
+ if regex.match(value)
56
+ UmfLogger.logInfoMsg("[UMF SDK]请求接口 service = "+ service +" 的参数值 "+ elem +" 正则校验通过")
57
+ else
58
+ UmfLogger.logInfoMsg("[UMF SDK]请求接口 service = "+ service +" 的参数值 "+ elem +" 正则校验未通过,对应的正则表达式为 regex = " + regex)
59
+ # UmfLogger.logInfoMsg("--------------------log end---------------------")
60
+ # exit
61
+ end
62
+ end
63
+ end
64
+ }
65
+ end
66
+
67
+
68
+ # 敏感字段加密
69
+ def doEncrypt(params)
70
+ chkKeys = [
71
+ "card_id",
72
+ "valid_date",
73
+ "cvv2",
74
+ "pass_wd",
75
+ "identity_code",
76
+ "card_holder",
77
+ "recv_account",
78
+ "recv_user_name",
79
+ "identity_holder",
80
+ "identityCode",
81
+ "cardHolder",
82
+ "mer_cust_name",
83
+ "account_name",
84
+ "bank_account",
85
+ "endDate",
86
+ ]
87
+ chkKeys.each{ |elem|
88
+ value = params[elem]
89
+ if value=="" || value==nil
90
+ next
91
+ end
92
+ UmfLogger.logInfoMsg("[UMF SDK]请求接口 service = " + params["service"] + " 的参数值 " + elem +" 是敏感字段需要进行RSA公钥加密")
93
+ # utf8 --> gbk
94
+ val = value.encode('gbk','utf-8')
95
+ params[elem] = UmfRSACryptUtil.new.encrypt(val)
96
+ }
97
+ return params
98
+ end
99
+
100
+ end
101
+
@@ -0,0 +1,24 @@
1
+ # UmfCommon
2
+ # author : zhaoyingxin
3
+
4
+
5
+ UMF_PAY_REQ_URL = "https://pay.soopay.net/spay/pay/payservice.do"
6
+ UMF_METHOD_GET = "get"
7
+ UMF_METHOD_POST = "post"
8
+
9
+ # 联动优势RSA公钥
10
+ UMF_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----
11
+ MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDGWAu4p6aK1SiQqNKT1nTgYwA8
12
+ cz0Rde9fRtmLJAx1QxLqrerAUVl/uuXV7NQFSkTipouo3cwEEpae89267AeLJBzK
13
+ PbKnUID6JYGbwnq7CiRR4E244zcgqE8jo8DnkbH3KkiWonoUMD1uHy6TUFv5W7zr
14
+ haz/E59MVmbzrp1TwwIDAQAB
15
+ -----END PUBLIC KEY-----"
16
+
17
+
18
+ # 子商户入网
19
+ UMF_RESTPAY_AUTHORIZE = "https://pay.soopay.net/spay_restPay/oauth/authorize"
20
+ UMF_RESTPAY_ADDCHILDMERINFO = "https://pay.soopay.net/spay_restPay/addChildMerInfo"
21
+ UMF_RESTPAY_UPLOADCHILDFILE = "https://pay.soopay.net/spay_restPay/uploadChildFile"
22
+ UMF_RESTPAY_CHANGECHILDREBUT = "https://pay.soopay.net/spay_restPay/changeChildRebut"
23
+ UMF_RESTPAY_SELECTCHILDMERSTATE = "https://pay.soopay.net/spay_restPay/selectChildMerState"
24
+
@@ -0,0 +1,39 @@
1
+ # UmfConfig
2
+ # author : zhaoyingxin
3
+
4
+ class UmfConfig
5
+ public
6
+ @@umf_log_switch = false
7
+ @@umf_log_path = ''
8
+ @@umf_mer_client_id = ''
9
+ @@umf_mer_client_secret = ''
10
+
11
+ def UmfConfig.umf_log_switch
12
+ @@umf_log_switch
13
+ end
14
+ def UmfConfig.umf_log_switch=(x)
15
+ @@umf_log_switch=x
16
+ end
17
+
18
+ def UmfConfig.umf_log_path
19
+ @@umf_log_path
20
+ end
21
+ def UmfConfig.umf_log_path=(x)
22
+ @@umf_log_path=x
23
+ end
24
+
25
+ def UmfConfig.umf_mer_client_id
26
+ @@umf_mer_client_id
27
+ end
28
+ def UmfConfig.umf_mer_client_id=(x)
29
+ @@umf_mer_client_id=x
30
+ end
31
+
32
+ def UmfConfig.umf_mer_client_secret
33
+ @@umf_mer_client_secret
34
+ end
35
+ def UmfConfig.umf_mer_client_secret=(x)
36
+ @@umf_mer_client_secret=x
37
+ end
38
+
39
+ end
@@ -0,0 +1,154 @@
1
+ # http client
2
+ # author : zhaoyingxin
3
+
4
+ # 服务端返回数据格式
5
+ # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
6
+ # <html>
7
+ # <head>
8
+ # <META NAME="MobilePayPlatform" CONTENT="amount=1&amt_type=RMB&bank_payurl=weixin://wxpay/bizpayurl?pr=MrAGkwR&mer_date=20171130&mer_id=60000100&mer_priv=&order_id=999999999&platDate=20171130&ret_code=0000&ret_msg=操作成功&sign_type=RSA&trade_state=WAIT_BUYER_PAY&version=4.0&sign=LHZELMiSZPfPccQoFe/0vTUmfDe5WCz7xSoIROwiPs63ZOdBq2ZcG9UL6JuNVrgJJuI75uNSVwj8asxso1dgy7a98l8Tp7Ftir48apDsyF7SZ5Dx1+9pxyr1WfrWipFN1SOsD9W/SnXxB3PDVZnn2jl8u2vablBgNGagGAlfLxo=">
9
+ # </head>
10
+ # <body>
11
+ # </body>
12
+ # </html>
13
+
14
+ require 'uri'
15
+ require 'cgi'
16
+ require 'net/http'
17
+ require 'net/https'
18
+ require 'json'
19
+
20
+ require 'UmfStringUtil'
21
+ require 'UmfRSACryptUtil'
22
+
23
+ class UmfHttp
24
+
25
+ # 向服务端发起GET请求
26
+ def httpGet(urlStr)
27
+
28
+ end
29
+
30
+
31
+ # 向服务端发起POST请求
32
+ def httpPost(urlStr, params)
33
+ uri = URI.parse(urlStr)
34
+ https = Net::HTTP.new(uri.host)
35
+ https.use_ssl = false
36
+ req = Net::HTTP::Post.new(uri.path)
37
+ param = UmfStringUtil.new.rasEncryptedStrEscape(params)
38
+ param = UmfStringUtil.new.getPlainSortByAnd(param)
39
+ UmfLogger.logInfoMsg("[UMF SDK]本次请求 service = " + params["service"] + " 对应的请求体 request.body = " + param)
40
+ req.body = param
41
+ res = https.request(req)
42
+ output = res.body #{res.code} #{res.message}: #{res.body}
43
+ UmfLogger.logInfoMsg("[UMF SDK]本次请求原始响应数据 " + output.force_encoding("utf-8"))
44
+ # 对账直接返回
45
+ if params["service"] == "download_settle_file"
46
+ UmfLogger.logInfoMsg("[UMF SDK] 对账接口返回原始响应数据 " + output)
47
+ return output
48
+ end
49
+ # 解析HTML返回 CONTENT
50
+ contentStr = parseHTMLStr(output)
51
+ contentArr = contentStr.split("&")
52
+ response = {}
53
+ contentArr.each { |elem|
54
+ arr = elem.split("=",2)
55
+ response[arr[0]] = arr[1]
56
+ }
57
+ UmfLogger.logInfoMsg("[UMF SDK]本次请求处理后返回的响应数据 " + response.to_s)
58
+ UmfLogger.logInfoMsg("--------------------log end---------------------")
59
+ response.delete('sign')
60
+ response.delete('sign_type')
61
+ response.delete('version')
62
+ return response
63
+ end
64
+
65
+
66
+
67
+ def parseHTMLStr(htmlStr)
68
+ if htmlStr.length <= 0
69
+ return
70
+ end
71
+ # MobilePayPlatform
72
+ regex = /CONTENT="([\w\W]*?)"/
73
+ content = regex.match(htmlStr).to_s.split("=",2)[1]
74
+ resParamsArr = content.split("&")
75
+ plain = ''
76
+ sign = ''
77
+ resParamsArr.each { |elem|
78
+ arr = elem.split("=",2)
79
+ if arr[0]=="sign_type"
80
+ next
81
+ end
82
+ if arr[0]=="sign"
83
+ sign = arr[1]
84
+ next
85
+ end
86
+ plain = plain + elem + "&"
87
+ }
88
+ plain = plain.chop
89
+ plain = plain.delete '"'
90
+ sign = sign.chop
91
+ begin
92
+ # plain utf8-->gbk
93
+ plain = plain.encode('gbk','utf-8')
94
+ rescue Encoding::UndefinedConversionError
95
+ puts $!.error_char.dump
96
+ p $!.error_char.encoding
97
+ end
98
+ verifyRet = UmfRSACryptUtil.new.verify(plain,sign,"sha1")
99
+ if verifyRet
100
+ puts "[UMF SDK] 平台响应数据验证签名成功"
101
+ return content
102
+ else
103
+ puts "[UMF SDK] 平台响应数据验证签名失败"
104
+ end
105
+ end
106
+
107
+
108
+ # ----------------------------------------
109
+ # 子商户入网部分
110
+ # ----------------------------------------
111
+ def httpRequestWithJson(urlStr,isPost,jsonParam,headers)
112
+ UmfLogger.logInfoMsg("[UMF SDK 子商户入网]本次请求对应的URL " + urlStr)
113
+ UmfLogger.logInfoMsg(isPost == true ? "[UMF SDK 子商户入网]本次请求方式 post" : "[UMF SDK 子商户入网]本次请求方式 get")
114
+ # if(strpos($urlStr, UMF_RESTPAY_UPLOADCHILDFILE) !== false){
115
+ # //上传文件接口 由于文件的二进制数据过大 不写入log
116
+ # }else{
117
+ # $log->logInfo("[UMF SDK 子商户入网]本次请求对应的json " .$jsonParam);
118
+ # }
119
+
120
+ uri = URI.parse(urlStr)
121
+ https = Net::HTTP.new(uri.host)
122
+ https.use_ssl = false
123
+ if isPost==true
124
+ req = Net::HTTP::Post.new(uri,headers)
125
+ req.body = jsonParam
126
+ res = https.request(req)
127
+ response = res.body
128
+ else isPost==false
129
+ req = Net::HTTP::Get.new(uri,headers)
130
+ res = https.request(req)
131
+ response = res.body
132
+ end
133
+ # 验签
134
+ arr = response.split('&',2)
135
+ if arr.length == 2
136
+ resPlain = arr[0]
137
+ resSign = arr[1]
138
+ verifyRet = UmfRSACryptUtil.new.verify(resPlain,resSign,'sha256')
139
+ if verifyRet == true
140
+ puts "[UMF SDK 子商户入网] 平台响应数据验证签名成功"
141
+ UmfLogger.logInfoMsg("[UMF SDK 子商户入网]本次请求原始响应数据 " + response.force_encoding('utf-8').to_s)
142
+ UmfLogger.logInfoMsg("--------------------log end---------------------")
143
+ return JSON.parse(resPlain)
144
+ else
145
+ puts "[UMF SDK 子商户入网] 平台响应数据验证签名失败"
146
+ end
147
+ elsif urlStr==UMF_RESTPAY_AUTHORIZE
148
+ return JSON.parse(response)
149
+ end
150
+ end
151
+
152
+
153
+ end
154
+
@@ -0,0 +1,25 @@
1
+ # UmfLogger
2
+ # author : zhaoyingxin
3
+
4
+
5
+ require 'logger'
6
+
7
+ require 'UmfConfig'
8
+
9
+ class UmfLogger
10
+
11
+ # 写入info类型日志到日志文件
12
+ def UmfLogger.logInfoMsg(msg)
13
+ if UmfConfig.umf_log_switch
14
+ filePath = UmfConfig.umf_log_path + "-" + Time.new.strftime("%Y-%m-%d") + ".txt"
15
+ #msgHead = Time.new.strftime("%Y-%m-%d %H:%M:%S") + " "
16
+ #msg = msgHead + msg
17
+ file = File.open(filePath, File::APPEND | File::CREAT | File::WRONLY)
18
+ logger = Logger.new(file)
19
+ logger.info(msg)
20
+ end
21
+ end
22
+
23
+
24
+ end
25
+
@@ -0,0 +1,17 @@
1
+ # MerToPlat util
2
+ # author : zhaoyingxin
3
+
4
+ require 'UmfReqDataUtil'
5
+
6
+ class UmfMerToPlat
7
+
8
+ def makeRequestDataByGet(param)
9
+ UmfReqDataUtil.new.makeRequestData(param,UMF_METHOD_GET)
10
+ end
11
+
12
+ def makeRequestDataByPost(param)
13
+ UmfReqDataUtil.new.makeRequestData(param,UMF_METHOD_POST)
14
+ end
15
+
16
+ end
17
+
@@ -0,0 +1,81 @@
1
+ # UmfRSACryptUtil
2
+ # author : zhaoyingxin
3
+ #
4
+ #
5
+
6
+
7
+ require 'openssl'
8
+ require 'base64'
9
+
10
+ require 'UmfCommon'
11
+ require 'UmfLogger'
12
+ require 'UmfService'
13
+
14
+
15
+ class UmfRSACryptUtil
16
+
17
+ # 使用公钥对明文字符串进行加密 data 明文字符串
18
+ def encrypt(data)
19
+ public_key = OpenSSL::PKey::RSA.new(UMF_PUBLIC_KEY)
20
+ encryptData = Base64.encode64(public_key.public_encrypt(data)).to_s.gsub(/\n/, '')
21
+ return encryptData
22
+ end
23
+
24
+
25
+ # rsa私钥签名
26
+ def sign(plain, merId, signType)
27
+ priv_key_file = $privateKeyPath[merId]
28
+ if !(File.exist?(priv_key_file))
29
+ UmfLogger.logInfoMsg("[UMF SDK]传入的私钥文件不存在,私钥文件绝对路径 " + priv_key_file)
30
+ exit
31
+ end
32
+ pkey = OpenSSL::PKey::RSA.new(File.read(priv_key_file))
33
+ signature = ""
34
+ if signType == "sha1"
35
+ signature = Base64.strict_encode64(pkey.sign(OpenSSL::Digest::SHA1.new, plain))
36
+ elsif signType == "sha256"
37
+ signature = Base64.strict_encode64(pkey.sign(OpenSSL::Digest::SHA256.new, plain))
38
+ end
39
+ UmfLogger.logInfoMsg("[UMF SDK]签名后密文 " + signature)
40
+ return signature
41
+ end
42
+
43
+
44
+ # 联动返回签名的验签
45
+ def verify(plain,sign,algorithmType)
46
+ public_key = OpenSSL::PKey::RSA.new(UMF_PUBLIC_KEY)
47
+ if algorithmType == "sha1"
48
+ verifyRet = public_key.verify(OpenSSL::Digest::SHA1.new, Base64.decode64(sign), plain)
49
+ elsif algorithmType == "sha256"
50
+ verifyRet = public_key.verify(OpenSSL::Digest::SHA256.new, Base64.decode64(sign), plain)
51
+ end
52
+ if verifyRet == true
53
+ # puts "[UMF SDK] 平台响应数据验签成功"
54
+ return true
55
+ elsif verifyRet == false
56
+ # puts "[UMF SDK] 平台响应数据验签失败"
57
+ return false
58
+ end
59
+ end
60
+
61
+
62
+ def mobileGenerateSign(plain,merId,signType)
63
+ priv_key_file = $privateKeyPath[merId]
64
+ if !(File.exist?(priv_key_file))
65
+ UmfLogger.logInfoMsg("[UMF SDK]传入的私钥文件不存在,私钥文件绝对路径 " + priv_key_file)
66
+ return
67
+ end
68
+ pkey = OpenSSL::PKey::RSA.new(File.read(priv_key_file))
69
+ signature = ""
70
+ if signType == "sha1"
71
+ signature = pkey.sign(OpenSSL::Digest::SHA1.new, plain).unpack("H*")[0].to_s.upcase
72
+ elsif signType == "sha256"
73
+
74
+ end
75
+ UmfLogger.logInfoMsg("[UMF SDK]签名后密文 " + signature)
76
+ return signature
77
+ end
78
+
79
+
80
+ end
81
+