Module: WechatPay::Sign
- Defined in:
- lib/wechat-pay/sign.rb
Overview
微信签名相关的封装
文档: https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_0.shtml
PS: 提供了常用的帮助方法,方便您的开发
Class Method Summary collapse
-
.build_authorization_header(method, url, json_body) ⇒ Object
Build authorization header for request.
-
.decrypt_the_encrypt_params(associated_data:, nonce:, ciphertext:) ⇒ Object
For Decrypting the encrypt params from wechat platform.
-
.generate_app_payment_params_from_prepay_id_and_appid(appid, prepay_id) ⇒ Object
Generate payment params with appid and prepay_id for invoking the wechat pay in app.
-
.generate_payment_params_from_prepay_id_and_appid(appid, prepay_id) ⇒ Object
Generate payment params with appid and prepay_id for invoking the wechat pay in miniprogram.
-
.notification_from_wechat?(timestamp, noncestr, json_body, signature) ⇒ Boolean
For checkingi if the requests from wechat platform.
-
.sign_important_info(string) ⇒ Object
For signing the sensitive information.
- .sign_string(string) ⇒ Object
Class Method Details
.build_authorization_header(method, url, json_body) ⇒ Object
Build authorization header for request
Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/wechatpay/wechatpay4_0.shtml
Usage:
method = 'GET'
url = '/v3/certificates'
json_body = ''
WechatPay::sign.(method, url, json_body)
# Result
"WECHATPAY2-SHA256-RSA2048 mchid=\"16000000\",nonce_str=\"42ac357637f9331794e0c6fb3b3de048\",serial_no=\"0254A801C0\",signature=\"WBJaWlVFur5OGQ/E0ZKIlSDhR8WTNrkW2oCECF3Udrh8BVlnfYf5N5ROeOt9PBxdwD0+ufFQANZKugmXDNat+sFRY2DrIzdP3qYvFIzaYjp6QEtB0UPzvTgcLDULGbwCSTNDxvKRDi07OXPFSmVfmA5SbpbfumgjYOfzt1wcl9Eh+/op/gAB3N010Iu1w4OggR78hxQvPb9GIscuKHjaUWqqwf6v+p3/b0tiSO/SekJa3bMKPhJ2wJj8utBHQtbGO+iUQj1n90naL25MNJUM2XYocv4MasxZZgZnV3v1dtRvFkVo0ApqFyDoiRndr1Q/jPh+wmsb80LuhZ1S4eNfew==\",timestamp=\"1620571488\""
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/wechat-pay/sign.rb', line 202 def (method, url, json_body) = Time.now.to_i nonce_str = SecureRandom.hex string = build_string(method, url, , nonce_str, json_body) signature = sign_string(string) params = { mchid: WechatPay.mch_id, nonce_str: nonce_str, serial_no: WechatPay.apiclient_serial_no, signature: signature, timestamp: } params_string = params.stringify_keys.map { |key, value| "#{key}=\"#{value}\"" }.join(',') "WECHATPAY2-SHA256-RSA2048 #{params_string}" end |
.decrypt_the_encrypt_params(associated_data:, nonce:, ciphertext:) ⇒ Object
For Decrypting the encrypt params from wechat platform
Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/wechatpay/wechatpay4_2.shtml
Usage:
def pay_action
# check if the request from wechat
associated_data = body['resource']['associated_data']
nonce = body['resource']['nonce']
ciphertext = body['resource']['ciphertext']
res = WechatPay::Sign.decrypt_the_encrypt_params(
associated_data: associated_data,
nonce: nonce,
ciphertext: ciphertext
)
result = JSON.parse(res) # Get the real params
end
170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/wechat-pay/sign.rb', line 170 def decrypt_the_encrypt_params(associated_data:, nonce:, ciphertext:) # https://contest-server.cs.uchicago.edu/ref/ruby_2_3_1_stdlib/libdoc/openssl/rdoc/OpenSSL/Cipher.html tag_length = 16 decipher = OpenSSL::Cipher.new('aes-256-gcm').decrypt decipher.key = WechatPay.mch_key decipher.iv = nonce signature = Base64.strict_decode64(ciphertext) length = signature.length real_signature = signature.slice(0, length - tag_length) tag = signature.slice(length - tag_length, length) decipher.auth_tag = tag decipher.auth_data = associated_data decipher.update(real_signature) end |
.generate_app_payment_params_from_prepay_id_and_appid(appid, prepay_id) ⇒ Object
Generate payment params with appid and prepay_id for invoking the wechat pay in app
Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_2_7.shtml
Take app for example
appid = 'appid for mobile'
params = {
sp_appid: 'Your appid',
sp_mchid: 'Your mchid',
description: 'pay',
out_trade_no: 'Order Number',
amount: {
total: 10
},
sub_mchid: 'Your sub mchid',
notify_url: 'the url'
}
result = WechatPay::Ecommerce.invoke_transactions_in_app(params).body
# => { prepay_id => 'wx201410272009395522657a690389285100' }
prepay_id = result['prepay_id']
WechatPay::Sign.generate_app_payment_params_from_prepay_id_and_appid(appid, prepay_id)
# => params for invoking the wechat pay in app
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/wechat-pay/sign.rb', line 43 def generate_app_payment_params_from_prepay_id_and_appid(appid, prepay_id) = Time.now.to_i.to_s noncestr = SecureRandom.hex string = build_app_paysign_string(appid, , noncestr, prepay_id) { appId: appid, partnerId: WechatPay.mch_id, timeStamp: , nonceStr: noncestr, prepayId: prepay_id, packageValue: 'Sign=WXPay', sign: sign_string(string) }.stringify_keys end |
.generate_payment_params_from_prepay_id_and_appid(appid, prepay_id) ⇒ Object
Generate payment params with appid and prepay_id for invoking the wechat pay in miniprogram
Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_2_8.shtml
Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_2_9.shtml
Take app for example
appid = 'appid for mobile'
params = {
sp_appid: 'Your appid',
sp_mchid: 'Your mchid',
description: 'pay',
out_trade_no: 'Order Number',
payer: {
sp_openid: 'wechat open id'
},
amount: {
total: 10
},
sub_mchid: 'Your sub mchid',
notify_url: 'the url'
}
result = WechatPay::Ecommerce.invoke_transactions_in_miniprogram(params).body
# => { prepay_id => 'wx201410272009395522657a690389285100' }
prepay_id = result['prepay_id']
WechatPay::Sign.generate_payment_params_from_prepay_id_and_appid(appid, prepay_id)
# => params for invoking the wechat pay in miniprogram
91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/wechat-pay/sign.rb', line 91 def generate_payment_params_from_prepay_id_and_appid(appid, prepay_id) = Time.now.to_i.to_s noncestr = SecureRandom.hex string = build_paysign_string(appid, , noncestr, prepay_id) { timeStamp: , nonceStr: noncestr, package: "prepay_id=#{prepay_id}", paySign: sign_string(string), signType: 'RSA' }.stringify_keys end |
.notification_from_wechat?(timestamp, noncestr, json_body, signature) ⇒ Boolean
For checkingi if the requests from wechat platform
Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_2_11.shtml
Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/wechatpay/wechatpay4_1.shtml
Usage:
def pay_action
= request.headers['Wechatpay-Timestamp']
noncestr = request.headers['Wechatpay-Nonce']
signature = request.headers['Wechatpay-Signature']
body = JSON.parse(request.body.read)
raise Exceptions::InvalidAction, '非法请求,请求并非来自微信' unless WechatV3.notification_from_wechat?(, noncestr, body.to_json, signature)
# ....
end
123 124 125 126 127 |
# File 'lib/wechat-pay/sign.rb', line 123 def notification_from_wechat?(, noncestr, json_body, signature) string = build_callback_string(, noncestr, json_body) decoded_signature = Base64.strict_decode64(signature) WechatPay.platform_cert.public_key.verify('SHA256', decoded_signature, string) end |
.sign_important_info(string) ⇒ Object
For signing the sensitive information
Document: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/wechatpay/wechatpay4_3.shtml
Usage:
string = 'Ruby'
WechatPay::Sign.sign_important_info(string)
# result
"K0MK7g3laREAQ4HIlpIndVmFdz4IyxxiVp42hXFx2CzWRB1fn85ANBxnQXESq91vJ1P9mCt94cHZDoshlEOJRkE1KvcxpBCnG3ghIqiSsLKdLZ3ytO94GBDzCt8nsq+vJKXJbK2XuL9p5h0KYGKZyjt2ydU9Ig6daWTpZH8lAKIsLzPTsaUtScuw/v3M/7t8/4py8N0MOLKbDBDnR5Q+MRHbEWI9nCA3HTAWsSerIIgE7igWnzybxsUzhkV8m49P/Shr2zh6yJAlEnyPLFmQG7GuUaYwDTSLKOWzzPYwxMcucWQha2krC9OlwnZJe6ZWUAI3s4ej4kFRfheOYywRoQ=="
144 145 146 147 |
# File 'lib/wechat-pay/sign.rb', line 144 def sign_important_info(string) platform_public_key = WechatPay.platform_cert.public_key Base64.strict_encode64(platform_public_key.public_encrypt(string, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)) end |
.sign_string(string) ⇒ Object
221 222 223 224 |
# File 'lib/wechat-pay/sign.rb', line 221 def sign_string(string) result = WechatPay.apiclient_key.sign('SHA256', string) # 商户私钥的SHA256-RSA2048签名 Base64.strict_encode64(result) # Base64处理 end |