{"id":16380999,"url":"https://github.com/jasl/wx_pay","last_synced_at":"2025-05-15T05:05:36.310Z","repository":{"id":23054758,"uuid":"26408013","full_name":"jasl/wx_pay","owner":"jasl","description":"An unofficial simple wechat pay gem","archived":false,"fork":false,"pushed_at":"2024-04-16T09:27:38.000Z","size":148,"stargazers_count":461,"open_issues_count":9,"forks_count":226,"subscribers_count":17,"default_branch":"master","last_synced_at":"2025-05-13T12:10:22.741Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jasl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"MIT-LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-11-09T20:25:41.000Z","updated_at":"2025-04-26T08:05:56.000Z","dependencies_parsed_at":"2024-04-16T10:41:02.488Z","dependency_job_id":"1ef10a84-dd81-4602-8f8b-b84a7d3c1464","html_url":"https://github.com/jasl/wx_pay","commit_stats":{"total_commits":151,"total_committers":43,"mean_commits":3.511627906976744,"dds":0.5562913907284768,"last_synced_commit":"d77e654f25cdf04913f2ff38d85777b8af219315"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jasl%2Fwx_pay","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jasl%2Fwx_pay/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jasl%2Fwx_pay/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jasl%2Fwx_pay/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jasl","download_url":"https://codeload.github.com/jasl/wx_pay/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254276446,"owners_count":22043866,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T03:53:06.508Z","updated_at":"2025-05-15T05:05:36.291Z","avatar_url":"https://github.com/jasl.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WxPay\n\nA simple Wechat pay ruby gem, without unnecessary magic or wrapper.\ncopied from [alipay](https://github.com/chloerei/alipay) .\n\nPlease read official document first: https://pay.weixin.qq.com/wiki/doc/api/index.html.\n\n[![Build Status](https://travis-ci.org/jasl/wx_pay.svg?branch=master)](https://travis-ci.org/jasl/wx_pay)\n\n## Installation\n\nAdd this line to your Gemfile:\n\n```ruby\ngem 'wx_pay'\n```\n\nor development version\n\n```ruby\ngem 'wx_pay', :github =\u003e 'jasl/wx_pay'\n```\n\nAnd then execute:\n\n```sh\n$ bundle\n```\n\n## Usage\n\n### Config\n\nCreate `config/initializers/wx_pay.rb` and put following configurations into it.\n\n```ruby\n# required\nWxPay.appid = 'YOUR_APPID'\nWxPay.key = 'YOUR_KEY'\nWxPay.mch_id = 'YOUR_MCH_ID' # required type is String, otherwise there will be cases where JS_PAY can pay but the APP cannot pay\nWxPay.debug_mode = true # default is `true`\n\n# cert, see https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=4_3\n# using PCKS12\nWxPay.set_apiclient_by_pkcs12(File.read(pkcs12_filepath), cert_password)\n\n# if you want to use `generate_authorize_req` and `authenticate`\nWxPay.appsecret = 'YOUR_SECRET' \n\n# optional - configurations for RestClient timeout, etc.\nWxPay.extra_rest_client_options = {timeout: 2, open_timeout: 3}\n```\n\n~~If you need to use sandbox mode.~~\n(Please be aware, the WeChat has aborted the sandbox env already)\n```ruby\nWxPay.appid = 'YOUR_APPID'\nWxPay.mch_id = 'YOUR_MCH_ID' # required type is String, otherwise there will be cases where JS_PAY can pay but the APP cannot pay\nWxPay.debug_mode = true # default is `true`\nWxPay.sandbox_mode = true # default is `false`\nresult = WxPay::Service.get_sandbox_signkey\nWxPay.key = result['sandbox_signkey']\n\n```\n\nNote: You should create your APIKEY (Link to [微信商户平台](https://pay.weixin.qq.com/index.php/home/login)) first if you haven't, and pay attention that **the length of the APIKEY should be 32**.\n\n### APIs\n\n**Check official document for detailed request params and return fields**\n\n#### unifiedorder\n\nWxPay supports MWEB, JSAPI, NATIVE and APP.\n\n```ruby\n# required fields\nparams = {\n  body: '测试商品',\n  out_trade_no: 'test003',\n  total_fee: 1,\n  spbill_create_ip: '127.0.0.1',\n  notify_url: 'http://making.dev/notify',\n  trade_type: 'JSAPI', # could be \"MWEB\", \"\"JSAPI\", \"NATIVE\" or \"APP\",\n  openid: 'OPENID' # required when trade_type is `JSAPI`\n}\n```\n\n`WxPay::Service.invoke_unifiedorder params` will create an payment request and return a WxPay::Result instance(subclass of Hash) contains parsed result.\n\nIf your trade type is \"MWEB\", the result would be like this.\n\n```ruby\nr = WxPay::Service.invoke_unifiedorder params\n# =\u003e {\n#      \"return_code\"=\u003e\"SUCCESS\",\n#      \"return_msg\"=\u003e\"OK\",\n#      \"appid\"=\u003e\"YOUR APPID\",\n#      \"mch_id\"=\u003e\"YOUR MCH_ID\",\n#      \"nonce_str\"=\u003e\"8RN7YfTZ3OUgWX5e\",\n#      \"sign\"=\u003e\"623AE90C9679729DDD7407DC7A1151B2\",\n#      \"result_code\"=\u003e\"SUCCESS\",\n#      \"prepay_id\"=\u003e\"wx2014111104255143b7605afb0314593866\",\n#      \"mweb_url\"=\u003e\"https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx2016121516420242444321ca0631331346\u0026package=1405458241\",\n#      \"trade_type\"=\u003e\"MWEB\"\n#    }\n```\n\nIf your trade type is \"JSAPI\", the result would be like this.\n\n```ruby\nr = WxPay::Service.invoke_unifiedorder params\n# =\u003e {\n#      \"return_code\"=\u003e\"SUCCESS\",\n#      \"return_msg\"=\u003e\"OK\",\n#      \"appid\"=\u003e\"YOUR APPID\",\n#      \"mch_id\"=\u003e\"YOUR MCH_ID\",\n#      \"nonce_str\"=\u003e\"8RN7YfTZ3OUgWX5e\",\n#      \"sign\"=\u003e\"623AE90C9679729DDD7407DC7A1151B2\",\n#      \"result_code\"=\u003e\"SUCCESS\",\n#      \"prepay_id\"=\u003e\"wx2014111104255143b7605afb0314593866\",\n#      \"trade_type\"=\u003e\"JSAPI\"\n#    }\n```\n\n\u003e \"JSAPI\" requires openid in params,\nin most cases I suggest you using [omniauth](https://github.com/omniauth/omniauth) with [omniauth-wechat-oauth2](https://github.com/skinnyworm/omniauth-wechat-oauth2) to resolve this,\nbut `wx_pay` provides `generate_authorize_url` and `authenticate` to help you get Wechat authorization in simple case.\n\nIf your trade type is \"NATIVE\", the result would be like this.\n\n```ruby\nr = WxPay::Service.invoke_unifiedorder params\n# =\u003e {\n#      \"return_code\"=\u003e\"SUCCESS\",\n#      \"return_msg\"=\u003e\"OK\",\n#      \"appid\"=\u003e\"YOUR APPID\",\n#      \"mch_id\"=\u003e\"YOUR MCH_ID\",\n#      \"nonce_str\"=\u003e\"8RN7YfTZ3OUgWX5e\",\n#      \"sign\"=\u003e\"623AE90C9679729DDD7407DC7A1151B2\",\n#      \"result_code\"=\u003e\"SUCCESS\",\n#      \"prepay_id\"=\u003e\"wx2014111104255143b7605afb0314593866\",\n#      \"code_url\"=\u003e\"weixin://\"\n#      \"trade_type\"=\u003e\"NATIVE\"\n#    }\n```\n\nReturn true if both `return_code` and `result_code` equal `SUCCESS`\n\n```ruby\nr.success? # =\u003e true\n```\n\n#### pay request for app\n\n```ruby\n# required fields\nparams = {\n  prepayid: '1101000000140415649af9fc314aa427', # fetch by call invoke_unifiedorder with `trade_type` is `APP`\n  noncestr: '1101000000140429eb40476f8896f4c9' # must same as given to invoke_unifiedorder\n}\n\n# call generate_app_pay_req\nr = WxPay::Service.generate_app_pay_req params\n# =\u003e {\n#      appid: 'wxd930ea5d5a258f4f',\n#      partnerid: '1900000109',\n#      prepayid: '1101000000140415649af9fc314aa427',\n#      package: 'Sign=WXPay',\n#      noncestr: '1101000000140429eb40476f8896f4c9',\n#      timestamp: '1398746574',\n#      sign: '7FFECB600D7157C5AA49810D2D8F28BC2811827B'\n#    }\n```\n\n#### pay request for JSAPI\n\n``` ruby\n# required fields\nparams = {\n  prepayid: '1101000000140415649af9fc314aa427', # fetch by call invoke_unifiedorder with `trade_type` is `JSAPI`\n  noncestr: SecureRandom.hex(16), \n}\n\n# call generate_js_pay_req\nr = WxPay::Service.generate_js_pay_req params\n# {\n#   \"appId\": \"wx020c5c792c8537de\",\n#   \"package\": \"prepay_id=wx20160902211806a11ccee7a20956539837\",\n#   \"nonceStr\": \"2vS5AJUD7uyaa5h9\",\n#   \"timeStamp\": \"1472822286\",\n#   \"signType\": \"MD5\",\n#   \"paySign\": \"A52433CB75CA8D58B67B2BB45A79AA01\"\n# }\n```\n\n#### Notify Process\n\nA simple example of processing notify for Rails Action Controller.\n\n```ruby\n# config/routes.rb\npost \"notify\" =\u003e \"orders#notify\"\n\n# app/controllers/orders_controller.rb\n\ndef notify\n  result = Hash.from_xml(request.body.read)[\"xml\"]\n\n  if WxPay::Sign.verify?(result)\n\n    # find your order and process the post-paid logic.\n\n    render :xml =\u003e {return_code: \"SUCCESS\"}.to_xml(root: 'xml', dasherize: false)\n  else\n    render :xml =\u003e {return_code: \"FAIL\", return_msg: \"签名失败\"}.to_xml(root: 'xml', dasherize: false)\n  end\nend\n```\n\nA simple example of processing notify for Grape v1.2.2 .\n\n```ruby\n# Gemfile\ngem 'multi_xml'\n\n# config/routes.rb\nmount WechatPay::Api =\u003e '/'\n\n# app/api/wechat_pay/api.rb\nmodule WechatPay\n  class Api \u003c Grape::API\n    content_type :xml, 'text/xml'\n    format :xml\n    formatter :xml, lambda { |object, env| object.to_xml(root: 'xml', dasherize: false) }\n    \n    post \"notify\" do\n      result = params[\"xml\"]\n      if WxPay::Sign.verify?(result)\n          # find your order and process the post-paid logic.\n          \n        status 200\n        {return_code: \"SUCCESS\"}\n      else\n        status 200\n        {return_code: \"FAIL\", return_msg: \"签名失败\"}\n      end\n    end\n  end\nend\n```\n\n\n### Integrate with QRCode(二维码)\n\nWechat payment integrating with QRCode is a recommended process flow which will bring users comfortable experience. It is recommended to generate QRCode using `rqrcode` and `rqrcode_png`.\n\n**Example Code** (please make sure that `public/uploads/qrcode` was created):\n\n```ruby\nr = WxPay::Service.invoke_unifiedorder params\nqrcode_png = RQRCode::QRCode.new( r[\"code_url\"], :size =\u003e 5, :level =\u003e :h ).to_img.resize(200, 200).save(\"public/uploads/qrcode/#{@order.id.to_s}_#{Time.now.to_i.to_s}.png\")\n@qrcode_url = \"/uploads/qrcode/#{@order.id.to_s}_#{Time.now.to_i.to_s}.png\"\n```\n\n### More\n\nNo documents yet, check `lib/wx_pay/service.rb`\n\n## Multi-account support\n\nAll functions have third argument `options`,\nyou can pass `appid`, `mch_id`, `key`, `apiclient_cert`, `apiclient_key` as a hash.\n\nFor example\n```ruby\nanother_account = {appid: 'APPID', mch_id: 'MCH_ID', key: 'KEY'}.freeze\nWxPay::Service.generate_app_pay_req params, another_account.dup\n```\n\n## Contributing\n\nBug report or pull request are welcome.\n\n### Make a pull request\n\n1. Fork it\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create new Pull Request\n\nPlease write unit test with your code if necessary.\n\n## License\n\nThis project rocks and uses MIT-LICENSE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjasl%2Fwx_pay","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjasl%2Fwx_pay","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjasl%2Fwx_pay/lists"}