wechat-ipay 2.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,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