wechat-ipay 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,195 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WechatPay
4
+ # 商户进件相关
5
+ module Ecommerce
6
+ # 二级商户进件
7
+ #
8
+ # Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter11_1_1.shtml
9
+ #
10
+ # Example:
11
+ #
12
+ # ``` ruby
13
+ # params = {
14
+ # "organization_type": "2",
15
+ # "business_license_info": {
16
+ # "business_license_copy": "47ZC6GC-vnrbEg05InE4d2I6_H7I4",
17
+ # "business_license_number": "123456789012345678",
18
+ # "merchant_name": "腾讯科技有限公司",
19
+ # "legal_person": "张三"
20
+ # },
21
+ # "organization_cert_info": {
22
+ # "organization_copy": "47ZC6GC-vnrbEny__Ie_An5-tCpqxuGprrKhpVBDIUv0OF4wFNIO4kqg05InE4d2I6_H7I4 ",
23
+ # "organization_time": "[\"2014-01-01\",\"长期\"]",
24
+ # "organization_number": "12345679-A"
25
+ # },
26
+ # "id_card_info": {
27
+ # "id_card_copy": "jTpGmxUX3FBWVQ5NJTZvlKC-ehEuo0BJqRTvDujqhThn4ReFxikqJ5YW6zFQ",
28
+ # "id_card_national": "47ZC6GC-vnrbEny__Ie_AnGprrKhpVBDIUv0OF4wFNIO4kqg05InE4d2I6_H7I4",
29
+ # "id_card_name": "pVd1HJ6z7UtC + xriudjD5AqhZ9evAM + Jv1z0NVa8MRtelw / wDa4SzfeespQO / 0 kjiwfqdfg =",
30
+ # "id_card_number": "UZFETyabYFFlgvGh6R4vTzDRgzvA2HtP5VHahNhSUqhR9iuGTunRPRVFg ==",
31
+ # "id_card_valid_time": "2026-06-06"
32
+ # },
33
+ # "need_account_info": true,
34
+ # "account_info": {
35
+ # "bank_account_type": "74",
36
+ # "account_name": "fTA4TXc8yMOwFCYeGPktOOSbOBei3KAmUWHGxCQo2hfaC7xumTqXR7 / NyRHpFKXURQFcmmw ==",
37
+ # "account_bank": "工商银行",
38
+ # "bank_address_code": "110000",
39
+ # "bank_branch_id": "402713354941",
40
+ # "bank_name": "施秉县农村信用合作联社城关信用社",
41
+ # "account_number": "d+xT+MQCvrLHUVD5Fnx30mr4L8sPndjXTd75kPkyjqnoMRrEEaYQE8ZRGYoeorwC"
42
+ # },
43
+ # "contact_info": {
44
+ # "contact_type": "65",
45
+ # "contact_name": "pVd1HJ6zyvPedzGaV+Xy7UDa4SzfeespQO / 0 kjiwfqdfg ==",
46
+ # "contact_id_card_number": "UZFETyabYFFlgvGh6R4vTzDEOiZZ4ka9+5RgzvA2rJx+NztYUbN209rqR9iuGTunRPRVFg ==",
47
+ # "mobile_phone": "Uy5Hb0c5Se/orEbrWze/ROHu9EPAs/CigDlJ2fnyzC1ppJNBrqcBszhYQUlu5zn6o2uZpBhAsQwd3QAjw==",
48
+ # "contact_email": "Uy5Hb0c5Se/orEbrWze/ROHu9EPAs/CigDlJ2fnyzC1ppJNaLZExOEzmUn6o2uZpBhAsQwd3QAjw=="
49
+ # },
50
+ # "sales_scene_info": {
51
+ # "store_name": "爱烧烤",
52
+ # "store_url": "http://www.qq.com",
53
+ # "store_qr_code": "jTpGmxUX3FBWVQ5NJTZvlKX_gdU4cRz7z5NxpnFuAujqhThn4ReFxikqJ5YW6zFQ"
54
+ # },
55
+ # "merchant_shortname": "爱烧烤",
56
+ # "out_request_no": "APPLYMENT_00000000001",
57
+ # "qualifications": "[\"jTpGmxUX3FBWVQ5NJInE4d2I6_H7I4\"]",
58
+ # "business_addition_pics": "[\"jTpGmg05InE4d2I6_H7I4\"]",
59
+ # "business_addition_desc": "特殊情况,说明原因"
60
+ # }
61
+ # ```
62
+ #
63
+ # ``` ruby
64
+ # WechatPay::Ecommerce.applyment(params)
65
+ # ```
66
+ #
67
+ def self.applyment(payload)
68
+ url = '/v3/ecommerce/applyments/'
69
+ method = 'POST'
70
+
71
+ payload_json = payload.to_json
72
+
73
+ make_request(
74
+ method: method,
75
+ path: url,
76
+ for_sign: payload_json,
77
+ payload: payload_json,
78
+ extra_headers: {
79
+ 'Wechatpay-Serial' => WechatPay.platform_serial_no
80
+ }
81
+ )
82
+ end
83
+
84
+ QUERY_APPLYMENT_FIELDS = %i[applyment_id out_request_no].freeze # :nodoc:
85
+ #
86
+ # 通过商户的申请单或微信的申请单号查询
87
+ #
88
+ # Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter11_1_2.shtml
89
+ #
90
+ # Example:
91
+ #
92
+ # ``` ruby
93
+ # WechatPay::Ecommerce.query_applyment(out_request_no: 'APPLYMENT_00000000005') # by out_request_no
94
+ # WechatPay::Ecommerce.query_applyment(applyment_id: '200040444455566667') # by_applyment_id
95
+ # ```
96
+ #
97
+ def self.query_applyment(params)
98
+ if params[:applyment_id]
99
+ applyment_id = params.delete(:applyment_id)
100
+ url = "/v3/ecommerce/applyments/#{applyment_id}"
101
+ else
102
+ out_request_no = params.delete(:out_request_no)
103
+ url = "/v3/ecommerce/applyments/out-request-no/#{out_request_no}"
104
+ end
105
+ method = 'GET'
106
+
107
+ make_request(
108
+ method: method,
109
+ path: url,
110
+ extra_headers: {
111
+ 'Content-Type' => 'application/x-www-form-urlencoded'
112
+ }
113
+ )
114
+ end
115
+
116
+ # 证书获取
117
+ #
118
+ # Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_1_3.shtml
119
+ #
120
+ # Example:
121
+ #
122
+ # ``` ruby
123
+ # WechatPay::Ecommerce.certificates
124
+ # ```
125
+ #
126
+ def self.certificates
127
+ url = '/v3/certificates'
128
+ method = 'GET'
129
+
130
+ make_request(
131
+ method: method,
132
+ path: url,
133
+ extra_headers: {
134
+ 'Content-Type' => 'application/x-www-form-urlencoded'
135
+ }
136
+ )
137
+ end
138
+
139
+ INVOKE_QUERY_SETTLEMENT_FIELDS = [:sub_mchid].freeze # :nodoc:
140
+ #
141
+ # 查询结算账户
142
+ #
143
+ # Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_1_5.shtml
144
+ #
145
+ # Example:
146
+ #
147
+ # ``` ruby
148
+ # WechatPay::Ecommerce.query_settlement(sub_mchid: '16000000')
149
+ # ```
150
+ #
151
+ def self.query_settlement(params)
152
+ sub_mchid = params.delete(:sub_mchid)
153
+ url = "/v3/apply4sub/sub_merchants/#{sub_mchid}/settlement"
154
+ method = 'GET'
155
+
156
+ make_request(
157
+ method: method,
158
+ path: url,
159
+ extra_headers: {
160
+ 'Content-Type' => 'application/x-www-form-urlencoded'
161
+ }
162
+ )
163
+ end
164
+
165
+ INVOKE_MODIFY_SETTLEMENT_FIELDS = %i[sub_mchid account_type account_bank bank_address_code account_number].freeze # :nodoc:
166
+ #
167
+ # 修改结算账号
168
+ #
169
+ # Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_1_4.shtml
170
+ #
171
+ # Example:
172
+ #
173
+ # ``` ruby
174
+ # WechatPay::Ecommerce.modify_settlement(sub_mchid: '15000000', account_type: 'ACCOUNT_TYPE_PRIVATE', account_bank: '工商银行', bank_address_code: '110000', account_number: WechatPay::Sign.sign_important_info('755555555'))
175
+ # ```
176
+ #
177
+ def self.modify_settlement(params)
178
+ sub_mchid = params.delete(:sub_mchid)
179
+ url = "/v3/apply4sub/sub_merchants/#{sub_mchid}/modify-settlement"
180
+ method = 'POST'
181
+
182
+ payload_json = params.to_json
183
+
184
+ make_request(
185
+ method: method,
186
+ path: url,
187
+ for_sign: payload_json,
188
+ payload: payload_json,
189
+ extra_headers: {
190
+ 'Wechatpay-Serial' => WechatPay.platform_serial_no
191
+ }
192
+ )
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WechatPay
4
+ # 余额相关
5
+ module Ecommerce
6
+ QUERY_REALTIME_BALANCE_FIELDS = [:sub_mchid].freeze # :nodoc:
7
+ #
8
+ # 余额实时查询
9
+ #
10
+ # Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_7_1.shtml
11
+ #
12
+ # Example:
13
+ #
14
+ # ``` ruby
15
+ # WechatPay::Ecommerce.query_realtime_balance(sub_mchid: '1600000')
16
+ # ```
17
+ def self.query_realtime_balance(params)
18
+ sub_mchid = params.delete(:sub_mchid)
19
+ url = "/v3/ecommerce/fund/balance/#{sub_mchid}"
20
+ method = 'GET'
21
+
22
+ make_request(
23
+ path: url,
24
+ method: method,
25
+ extra_headers: {
26
+ 'Content-Type' => 'application/x-www-form-urlencoded'
27
+ }
28
+ )
29
+ end
30
+
31
+ QUERY_ENDDAY_BALANCE_FIELDS = %i[sub_mchid date].freeze # :nodoc:
32
+ #
33
+ # 日终余额查询
34
+ #
35
+ # Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_7_2.shtml
36
+ #
37
+ # Example:
38
+ #
39
+ # ``` ruby
40
+ # WechatPay::Ecommerce.query_endday_balance(sub_mchid: '1600000', date: '2019-08-17')
41
+ # ```
42
+ def self.query_endday_balance(params)
43
+ sub_mchid = params.delete(:sub_mchid)
44
+ path = "/v3/ecommerce/fund/balance/#{sub_mchid}"
45
+ method = 'GET'
46
+ query = build_query(params)
47
+ url = "#{path}?#{query}"
48
+
49
+ make_request(
50
+ path: url,
51
+ method: method,
52
+ extra_headers: {
53
+ 'Content-Type' => 'application/x-www-form-urlencoded'
54
+ }
55
+ )
56
+ end
57
+
58
+ QUERY_PLATFORM_REALTIME_BALANCE_FIELDS = %i[account_type].freeze # :nodoc:
59
+ #
60
+ # 平台商户实时余额
61
+ #
62
+ # Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_7_3.shtml
63
+ #
64
+ # Example:
65
+ #
66
+ # ``` ruby
67
+ # WechatPay::Ecommerce.query_platform_realtime_balance(account_type: 'BASIC') # basic account
68
+ # WechatPay::Ecommerce.query_platform_realtime_balance(account_type: 'FEES') # fees account
69
+ # ```
70
+ #
71
+ def self.query_platform_realtime_balance(params)
72
+ account_type = params.delete(:account_type)
73
+ url = "/v3/merchant/fund/balance/#{account_type}"
74
+ method = 'GET'
75
+
76
+ make_request(
77
+ path: url,
78
+ method: method,
79
+ extra_headers: {
80
+ 'Content-Type' => 'application/x-www-form-urlencoded'
81
+ }
82
+ )
83
+ end
84
+
85
+ QUERY_PLATFORM_ENDDAY_BALANCE_FIELDS = %i[account_type date].freeze # :nodoc:
86
+ #
87
+ # 平台商户日终余额
88
+ #
89
+ # Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_7_4.shtml
90
+ #
91
+ # Example:
92
+ #
93
+ # ``` ruby
94
+ # WechatPay::Ecommerce.query_platform_endday_balance(account_type: 'BASIC')
95
+ # WechatPay::Ecommerce.query_platform_endday_balance(account_type: 'FEES')
96
+ # ```
97
+ #
98
+ def self.query_platform_endday_balance(params)
99
+ account_type = params.delete(:account_type)
100
+ path = "/v3/merchant/fund/dayendbalance/#{account_type}"
101
+ method = 'GET'
102
+ query = build_query(params)
103
+ url = "#{path}?#{query}"
104
+
105
+ make_request(
106
+ path: url,
107
+ method: method,
108
+ extra_headers: {
109
+ 'Content-Type' => 'application/x-www-form-urlencoded'
110
+ }
111
+ )
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WechatPay
4
+ # 账单相关
5
+ module Ecommerce
6
+ class << self
7
+ TRADEBILL_FIELDS = [:bill_date].freeze # :nodoc:
8
+ #
9
+ # 申请交易账单
10
+ #
11
+ # Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_9_1.shtml
12
+ #
13
+ # Example:
14
+ #
15
+ # ``` ruby
16
+ # WechatPay::Ecommerce.tradebill(bill_date: '2021-04-30')
17
+ # ```
18
+ def tradebill(params)
19
+ path = '/v3/bill/tradebill'
20
+ method = 'GET'
21
+
22
+ query = build_query(params)
23
+ url = "#{path}?#{query}"
24
+
25
+ make_request(
26
+ path: url,
27
+ method: method,
28
+ extra_headers: {
29
+ 'Content-Type' => 'application/x-www-form-urlencoded'
30
+ }
31
+ )
32
+ end
33
+
34
+ FUNDFLOWBILL_FIELDS = [:bill_date].freeze # :nodoc:
35
+ #
36
+ # 申请资金账单
37
+ #
38
+ # Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_9_2.shtml
39
+ #
40
+ # Example:
41
+ #
42
+ # ``` ruby
43
+ # WechatPay::Ecommerce.fundflowbill(bill_date: '2021-04-30')
44
+ # ```
45
+ #
46
+ def fundflowbill(params)
47
+ path = '/v3/bill/fundflowbill'
48
+ method = 'GET'
49
+
50
+ query = build_query(params)
51
+ url = "#{path}?#{query}"
52
+
53
+ make_request(
54
+ path: url,
55
+ method: method,
56
+ extra_headers: {
57
+ 'Content-Type' => 'application/x-www-form-urlencoded'
58
+ }
59
+ )
60
+ end
61
+
62
+ ECOMMERCE_FUNDFLOWBILL_FIELDS = %i[bill_date account_type algorithm].freeze # :nodoc:
63
+ #
64
+ # 二级商户资金账单
65
+ #
66
+ # Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_9_5.shtml
67
+ #
68
+ # Example:
69
+ #
70
+ # ``` ruby
71
+ # WechatPay::Ecommerce.ecommerce_fundflowbill(bill_date: '2021-04-30', account_type: 'ALL', algorithm: 'AEAD_AES_256_GCM')
72
+ # ```
73
+ #
74
+ def ecommerce_fundflowbill(params)
75
+ path = '/v3/ecommerce/bill/fundflowbill'
76
+ method = 'GET'
77
+
78
+ query = build_query(params)
79
+ url = "#{path}?#{query}"
80
+
81
+ make_request(
82
+ path: url,
83
+ method: method,
84
+ extra_headers: {
85
+ 'Content-Type' => 'application/x-www-form-urlencoded'
86
+ }
87
+ )
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WechatPay
4
+ # 合并订单相关
5
+ module Ecommerce
6
+ # @private
7
+ # @!macro [attach] define_transaction_method
8
+ # $1合单
9
+ #
10
+ # Document: $3
11
+ #
12
+ # Example:
13
+ #
14
+ # ``` ruby
15
+ # params = {
16
+ # combine_out_trade_no: 'combine_out_trade_no',
17
+ # combine_payer_info: {
18
+ # openid: 'client open id'
19
+ # },
20
+ # sub_orders: [
21
+ # {
22
+ # mchid: 'mchid',
23
+ # sub_mchid: 'sub mchid',
24
+ # attach: 'attach',
25
+ # amount: {
26
+ # total_amount: 100,
27
+ # currency: 'CNY'
28
+ # },
29
+ # out_trade_no: 'out_trade_no',
30
+ # description: 'description'
31
+ # }
32
+ # ],
33
+ # notify_url: 'the_url'
34
+ # }
35
+ #
36
+ # WechatPay::Ecommerce.invoke_combine_transactions_in_$1(params)
37
+ # ```
38
+ # @!method invoke_combine_transactions_in_$1
39
+ # @!scope class
40
+ def self.define_combine_transaction_method(key, value, _document)
41
+ const_set("INVOKE_COMBINE_TRANSACTIONS_IN_#{key.upcase}_FIELDS",
42
+ %i[combine_out_trade_no combine_payer_info sub_orders notify_url].freeze)
43
+ define_singleton_method("invoke_combine_transactions_in_#{key}") do |params|
44
+ combine_transactions_method_by_suffix(value, params)
45
+ end
46
+ end
47
+
48
+ define_combine_transaction_method('js', 'jsapi', 'https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_3_3.shtml')
49
+ define_combine_transaction_method('h5', 'h5', 'https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_3_2.shtml')
50
+ define_combine_transaction_method('native', 'native', 'https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_3_5.shtml')
51
+ define_combine_transaction_method('app', 'app', 'https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_3_1.shtml')
52
+ define_combine_transaction_method('miniprogram', 'jsapi', 'https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_3_4.shtml')
53
+
54
+ QUERY_COMBINE_ORDER_FIELDS = %i[combine_out_trade_no].freeze # :nodoc:
55
+ #
56
+ # 合单查询
57
+ #
58
+ # Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_3_11.shtml
59
+ #
60
+ # ``` ruby
61
+ # WechatPay::Ecommerce.query_order(combine_out_trade_no: 'C202104302474')
62
+ # ```
63
+ #
64
+ def self.query_combine_order(params)
65
+ combine_out_trade_no = params.delete(:combine_out_trade_no)
66
+
67
+ url = "/v3/combine-transactions/out-trade-no/#{combine_out_trade_no}"
68
+
69
+ method = 'GET'
70
+
71
+ make_request(
72
+ method: method,
73
+ path: url,
74
+ extra_headers: {
75
+ 'Content-Type' => 'application/x-www-form-urlencoded'
76
+ }
77
+ )
78
+ end
79
+
80
+ CLOSE_COMBINE_ORDER_FIELDS = %i[combine_out_trade_no sub_orders].freeze # :nodoc:
81
+ #
82
+ # 关闭合单
83
+ #
84
+ # Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_3_11.shtml
85
+ #
86
+ # ``` ruby
87
+ # WechatPay::Ecommerce.close_combine_order(combine_out_trade_no: 'C202104302474')
88
+ # ```
89
+ def self.close_combine_order(params)
90
+ combine_out_trade_no = params.delete(:combine_out_trade_no)
91
+
92
+ url = "/v3/combine-transactions/out-trade-no/#{combine_out_trade_no}/close"
93
+
94
+ payload = {
95
+ combine_appid: WechatPay.app_id
96
+ }.merge(params)
97
+
98
+ payload_json = payload.to_json
99
+
100
+ method = 'POST'
101
+
102
+ make_request(
103
+ method: method,
104
+ for_sign: payload_json,
105
+ payload: payload_json,
106
+ path: url
107
+ )
108
+ end
109
+
110
+ class << self
111
+ private
112
+
113
+ def combine_transactions_method_by_suffix(suffix, params)
114
+ url = "/v3/combine-transactions/#{suffix}"
115
+ method = 'POST'
116
+
117
+ params = {
118
+ combine_mchid: WechatPay.mch_id,
119
+ combine_appid: WechatPay.app_id
120
+ }.merge(params)
121
+
122
+ payload_json = params.to_json
123
+
124
+ make_request(
125
+ method: method,
126
+ path: url,
127
+ for_sign: payload_json,
128
+ payload: payload_json
129
+ )
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WechatPay
4
+ # 订单相关
5
+ module Ecommerce
6
+ # @private
7
+ # @!macro [attach] define_transaction_method
8
+ # $1下单
9
+ #
10
+ # Document: $3
11
+ #
12
+ # Example:
13
+ #
14
+ # ```
15
+ # params = {
16
+ # description: 'pay',
17
+ # out_trade_no: 'Order Number',
18
+ # payer: {
19
+ # sp_openid: 'wechat open id'
20
+ # },
21
+ # amount: {
22
+ # total: 10
23
+ # },
24
+ # sub_mchid: 'Your sub mchid',
25
+ # notify_url: 'the url'
26
+ # }
27
+ #
28
+ # WechatPay::Ecommerce.invoke_transactions_in_$1(params)
29
+ # ```
30
+ # @!method invoke_transactions_in_$1
31
+ # @!scope class
32
+ def self.define_transaction_method(key, value, _document)
33
+ const_set("INVOKE_TRANSACTIONS_IN_#{key.upcase}_FIELDS",
34
+ %i[sub_mchid description out_trade_no notify_url amount].freeze)
35
+ define_singleton_method("invoke_transactions_in_#{key}") do |params|
36
+ transactions_method_by_suffix(value, params)
37
+ end
38
+ end
39
+
40
+ define_transaction_method('native', 'native', 'document missing')
41
+ define_transaction_method('js', 'jsapi', 'https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_2_2.shtml')
42
+ define_transaction_method('app', 'app', 'https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_2_1.shtml')
43
+ define_transaction_method('h5', 'h5', 'https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_2_4.shtml')
44
+ define_transaction_method('miniprogram', 'jsapi', 'https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_2_3.shtml')
45
+
46
+ QUERY_ORDER_FIELDS = %i[sub_mchid out_trade_no transaction_id].freeze # :nodoc:
47
+ #
48
+ # 订单查询
49
+ #
50
+ # Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_2_5.shtml
51
+ #
52
+ # ``` ruby
53
+ # WechatPay::Ecommerce.query_order(sub_mchid: '16000008', transaction_id: '4323400972202104305133344444') # by transaction_id
54
+ # WechatPay::Ecommerce.query_order(sub_mchid: '16000008', out_trade_no: 'N202104302474') # by out_trade_no
55
+ # ```
56
+ #
57
+ def self.query_order(params)
58
+ if params[:transaction_id]
59
+ params.delete(:out_trade_no)
60
+ transaction_id = params.delete(:transaction_id)
61
+ path = "/v3/pay/partner/transactions/id/#{transaction_id}"
62
+ else
63
+ params.delete(:transaction_id)
64
+ out_trade_no = params.delete(:out_trade_no)
65
+ path = "/v3/pay/partner/transactions/out-trade-no/#{out_trade_no}"
66
+ end
67
+
68
+ params = params.merge({
69
+ sp_mchid: WechatPay.mch_id
70
+ })
71
+
72
+ method = 'GET'
73
+ query = build_query(params)
74
+ url = "#{path}?#{query}"
75
+
76
+ make_request(
77
+ method: method,
78
+ path: url,
79
+ extra_headers: {
80
+ 'Content-Type' => 'application/x-www-form-urlencoded'
81
+ }
82
+ )
83
+ end
84
+
85
+ CLOSE_ORDER_FIELDS = %i[sub_mchid out_trade_no].freeze # :nodoc:
86
+ #
87
+ # 关闭订单
88
+ #
89
+ # Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_2_6.shtml
90
+ #
91
+ # ``` ruby
92
+ # WechatPay::Ecommerce.close_order(sub_mchid: '16000008', out_trade_no: 'N3344445')
93
+ # ```
94
+ #
95
+ def self.close_order(params)
96
+ out_trade_no = params.delete(:out_trade_no)
97
+ url = "/v3/pay/partner/transactions/out-trade-no/#{out_trade_no}/close"
98
+ params = params.merge({
99
+ sp_mchid: WechatPay.mch_id
100
+ })
101
+
102
+ method = 'POST'
103
+
104
+ make_request(
105
+ method: method,
106
+ path: url,
107
+ for_sign: params.to_json,
108
+ payload: params.to_json
109
+ )
110
+ end
111
+
112
+ class << self
113
+ private
114
+
115
+ def transactions_method_by_suffix(suffix, params)
116
+ url = "/v3/pay/partner/transactions/#{suffix}"
117
+ method = 'POST'
118
+
119
+ params = {
120
+ sp_appid: WechatPay.app_id,
121
+ sp_mchid: WechatPay.mch_id
122
+ }.merge(params)
123
+
124
+ payload_json = params.to_json
125
+
126
+ make_request(
127
+ method: method,
128
+ path: url,
129
+ for_sign: payload_json,
130
+ payload: payload_json
131
+ )
132
+ end
133
+ end
134
+ end
135
+ end