wechat-pay 1.0.1

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,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'wechat-pay/helper'
5
+ require 'wechat-pay/ecommerce/withdraw'
6
+ require 'wechat-pay/ecommerce/balance'
7
+ require 'wechat-pay/ecommerce/applyment'
8
+ require 'wechat-pay/ecommerce/order'
9
+ require 'wechat-pay/ecommerce/combine_order'
10
+ require 'wechat-pay/ecommerce/profitsharing'
11
+ require 'wechat-pay/ecommerce/subsidies'
12
+ require 'wechat-pay/ecommerce/refund'
13
+ require 'wechat-pay/ecommerce/bill'
14
+
15
+ module WechatPay
16
+ # # 服务商相关接口封装(电商平台,服务商有许多接口共用)
17
+ # 文档: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/open/pay/chapter3_3_3.shtml
18
+ #
19
+ # PS: 电商收付通的所有接口已经封装完毕,有需要再补充。
20
+ #
21
+ module Ecommerce
22
+ include WechatPayHelper
23
+
24
+ class<<self
25
+ # 视频上传
26
+ #
27
+ # Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter2_1_2.shtml
28
+ #
29
+ # Example:
30
+ #
31
+ # ``` ruby
32
+ # WechatPay::Ecommerce.media_video_upload(File.open('Your Video'))
33
+ # ```
34
+ #
35
+ def media_video_upload(video)
36
+ url = '/v3/merchant/media/video_upload'
37
+ method = 'POST'
38
+ meta = {
39
+ filename: video.to_path,
40
+ sha256: Digest::SHA256.hexdigest(video.read)
41
+ }
42
+
43
+ video.rewind
44
+ payload = {
45
+ meta: meta.to_json,
46
+ file: video
47
+ }
48
+
49
+ make_request(
50
+ method: method,
51
+ path: url,
52
+ for_sign: meta.to_json,
53
+ payload: payload,
54
+ extra_headers: {
55
+ 'Content-Type' => nil
56
+ }
57
+ )
58
+ end
59
+
60
+ # 图片上传
61
+ #
62
+ # Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter2_1_1.shtml
63
+ #
64
+ # Example:
65
+ #
66
+ # ``` ruby
67
+ # WechatPay::Ecommerce.media_upload(File.open('Your Image'))
68
+ # ```
69
+ def media_upload(image)
70
+ url = '/v3/merchant/media/upload'
71
+ method = 'POST'
72
+ meta = {
73
+ filename: image.to_path,
74
+ sha256: Digest::SHA256.hexdigest(image.read)
75
+ }
76
+
77
+ image.rewind
78
+ payload = {
79
+ meta: meta.to_json,
80
+ file: image
81
+ }
82
+
83
+ make_request(
84
+ method: method,
85
+ path: url,
86
+ for_sign: meta.to_json,
87
+ payload: payload,
88
+ extra_headers: {
89
+ 'Content-Type' => nil # Pass nil to remove the Content-Type
90
+ }
91
+ )
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,196 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WechatPay
4
+ module Ecommerce
5
+ class << self
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 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 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.get_certificates
124
+ # ```
125
+ #
126
+ def get_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 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 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
196
+ end
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WechatPay
4
+ module Ecommerce
5
+ class<<self
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 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 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 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 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
115
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WechatPay
4
+ module Ecommerce
5
+ class<<self
6
+ TRADEBILL_FIELDS = [:bill_date].freeze # :nodoc:
7
+ #
8
+ # 申请交易账单
9
+ #
10
+ # Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_9_1.shtml
11
+ #
12
+ # Example:
13
+ #
14
+ # ``` ruby
15
+ # WechatPay::Ecommerce.tradebill(bill_date: '2021-04-30')
16
+ # ```
17
+ def tradebill(params)
18
+ path = '/v3/bill/tradebill'
19
+ method = 'GET'
20
+
21
+ query = build_query(params)
22
+ url = "#{path}?#{query}"
23
+
24
+ make_request(
25
+ path: url,
26
+ method: method,
27
+ extra_headers: {
28
+ 'Content-Type' => 'application/x-www-form-urlencoded'
29
+ }
30
+ )
31
+ end
32
+
33
+ FUNDFLOWBILL_FIELDS = [:bill_date].freeze # :nodoc:
34
+ #
35
+ # 申请资金账单
36
+ #
37
+ # Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_9_2.shtml
38
+ #
39
+ # Example:
40
+ #
41
+ # ``` ruby
42
+ # WechatPay::Ecommerce.fundflowbill(bill_date: '2021-04-30')
43
+ # ```
44
+ #
45
+ def fundflowbill(params)
46
+ path = '/v3/bill/fundflowbill'
47
+ method = 'GET'
48
+
49
+ query = build_query(params)
50
+ url = "#{path}?#{query}"
51
+
52
+ make_request(
53
+ path: url,
54
+ method: method,
55
+ extra_headers: {
56
+ 'Content-Type' => 'application/x-www-form-urlencoded'
57
+ }
58
+ )
59
+ end
60
+
61
+ ECOMMERCE_FUNDFLOWBILL_FIELDS = %i[bill_date account_type algorithm].freeze # :nodoc:
62
+ #
63
+ # 二级商户资金账单
64
+ #
65
+ # Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_9_5.shtml
66
+ #
67
+ # Example:
68
+ #
69
+ # ``` ruby
70
+ # WechatPay::Ecommerce.ecommerce_fundflowbill(bill_date: '2021-04-30', account_type: 'ALL', algorithm: 'AEAD_AES_256_GCM')
71
+ # ```
72
+ #
73
+ def ecommerce_fundflowbill(params)
74
+ path = '/v3/ecommerce/bill/fundflowbill'
75
+ method = 'GET'
76
+
77
+ query = build_query(params)
78
+ url = "#{path}?#{query}"
79
+
80
+ make_request(
81
+ path: url,
82
+ method: method,
83
+ extra_headers: {
84
+ 'Content-Type' => 'application/x-www-form-urlencoded'
85
+ }
86
+ )
87
+ end
88
+ end
89
+ end
90
+ end