service.rb
4.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
require 'rest_client'
require 'active_support/core_ext/hash/conversions'
module WxPay
module Service
GATEWAY_URL = 'https://api.mch.weixin.qq.com'
INVOKE_UNIFIEDORDER_REQUIRED_FIELDS = %i(body out_trade_no total_fee spbill_create_ip notify_url trade_type)
def self.invoke_unifiedorder(params)
params = {
appid: WxPay.appid,
mch_id: WxPay.mch_id,
nonce_str: SecureRandom.uuid.tr('-', '')
}.merge(params)
check_required_options(params, INVOKE_UNIFIEDORDER_REQUIRED_FIELDS)
r = invoke_remote("#{GATEWAY_URL}/pay/unifiedorder", make_payload(params))
yield r if block_given?
r
end
GENERATE_APP_PAY_REQ_REQUIRED_FIELDS = %i(prepayid noncestr)
def self.generate_app_pay_req(params)
params = {
appid: WxPay.appid,
partnerid: WxPay.mch_id,
package: 'Sign=WXPay',
timestamp: Time.now.to_i.to_s
}.merge(params)
check_required_options(params, GENERATE_APP_PAY_REQ_REQUIRED_FIELDS)
params[:sign] = WxPay::Sign.generate(params)
params
end
INVOKE_REFUND_REQUIRED_FIELDS = %i(transaction_id out_trade_no out_refund_no total_fee refund_fee)
def self.invoke_refund(params)
params = {
appid: WxPay.appid,
mch_id: WxPay.mch_id,
nonce_str: SecureRandom.uuid.tr('-', ''),
op_user_id: WxPay.mch_id
}.merge(params)
check_required_options(params, INVOKE_REFUND_REQUIRED_FIELDS)
# 微信退款需要双向证书
# https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
# https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3
WxPay.extra_rest_client_options = {
ssl_client_cert: WxPay.apiclient_cert.certificate,
ssl_client_key: WxPay.apiclient_cert.key,
verify_ssl: OpenSSL::SSL::VERIFY_NONE
}
r = invoke_remote "#{GATEWAY_URL}/secapi/pay/refund", make_payload(params)
yield(r) if block_given?
r
end
INVOKE_REVERSE_REQUIRED_FIELDS = %i(out_trade_no)
def self.invoke_reverse(params)
params = {
appid: WxPay.appid,
mch_id: WxPay.mch_id,
nonce_str: SecureRandom.uuid.tr('-', '')
}.merge(params)
check_required_options(params, INVOKE_REVERSE_REQUIRED_FIELDS)
# 微信退款需要双向证书
# https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
# https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3
WxPay.extra_rest_client_options = {
ssl_client_cert: WxPay.apiclient_cert.certificate,
ssl_client_key: WxPay.apiclient_cert.key,
verify_ssl: OpenSSL::SSL::VERIFY_NONE
}
r = invoke_remote "#{GATEWAY_URL}/secapi/pay/reverse", make_payload(params)
yield(r) if block_given?
r
end
INVOKE_MICROPAY_REQUIRED_FIELDS = %i(body out_trade_no total_fee spbill_create_ip auth_code)
def self.invoke_micropay(params)
params = {
appid: WxPay.appid,
mch_id: WxPay.mch_id,
nonce_str: SecureRandom.uuid.tr('-', '')
}.merge(params)
puts params
check_required_options(params, INVOKE_MICROPAY_REQUIRED_FIELDS)
r = invoke_remote "#{GATEWAY_URL}/pay/micropay", make_payload(params)
yield(r) if block_given?
r
end
ORDER_QUERY_REQUIRED_FIELDS = %i(out_trade_no)
def self.order_query(params)
params = {
appid: WxPay.appid,
mch_id: WxPay.mch_id,
nonce_str: SecureRandom.uuid.tr('-', '')
}.merge(params)
puts params
check_required_options(params, ORDER_QUERY_REQUIRED_FIELDS)
r = invoke_remote "#{GATEWAY_URL}/pay/orderquery", make_payload(params)
yield(r) if block_given?
r
end
private
def self.check_required_options(options, names)
names.each do |name|
warn("WxPay Warn: missing required option: #{name}") unless options.has_key?(name)
end
end
def self.make_payload(params)
sign = WxPay::Sign.generate(params)
params.delete(:key) if params[:key]
"<xml>#{params.map { |k, v| "<#{k}>#{v}</#{k}>" }.join}<sign>#{sign}</sign></xml>"
end
def self.invoke_remote(url, payload)
r = RestClient::Request.execute(
{
method: :post,
url: url,
payload: payload,
headers: { content_type: 'application/xml' }
}.merge(WxPay.extra_rest_client_options)
)
if r
WxPay::Result.new Hash.from_xml(r)
else
nil
end
end
end
end