active_merchant_spgateway 0.0.3 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 3f687d8f4c8c0f658720f9508db7c1978118b1c2
4
- data.tar.gz: 12fec891fc8b8e3a8b98fe70f0d83e4848b189c6
2
+ SHA256:
3
+ metadata.gz: f33a33550d331f955ae19cd2ea61e1f3f4ed2a891ed542ece1b982f3f8bab59b
4
+ data.tar.gz: c396c1c3e26157e1a3552e2ac80f4c9f694cc09f58aca8b39d46c4e50eb52a49
5
5
  SHA512:
6
- metadata.gz: 5e28cfa362b7a06d7de47c2864dd39e7af73ea68d061422982377b0b5d439ec12afbeaded19c2f128d5db22fe03b4a757a0fe6ec3d1d61c53994358aa007dfb9
7
- data.tar.gz: 814e386b37e61776b037dad684ebdb9404389077722b552a222177c74d40288e2d24bb71c087c68b3fb6f18fd64eb5e5d2a53261e076576d662a488f36efba7f
6
+ metadata.gz: afcc6267937b9834ccdecea905c0ca8c457c88fe17a47f99dff46bc1368cb77e1a4529532d31c547e490f9baf6ff1c26fcad2d9629e10da0563f1d17e889ac4d
7
+ data.tar.gz: f41667a2ec68cfe32163e793ac006ace54382b485b9a6c55ed9e3b9a408e8780855e272754a35661b4f490e4c63a7418ce96d7238b7446db13f2bc4c92aeb28d
@@ -0,0 +1,121 @@
1
+ name: Publish gem
2
+
3
+ # master 上 gemspec 版本號尚未發佈到 rubygems.org 時,自動以 Trusted Publishing (OIDC) 發佈。
4
+ # 版本已存在則跳過;不使用任何儲存的 RubyGems API key。
5
+ on:
6
+ push:
7
+ branches:
8
+ - master
9
+ workflow_dispatch:
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ concurrency:
15
+ group: publish-gem-${{ github.repository }}
16
+ cancel-in-progress: false
17
+
18
+ env:
19
+ # 與 test.yml 矩陣中的 Ruby 3.4 / Rails 8.0 組合一致(gemfiles/ 的 lockfile 不納入版控,由 CI 解析)
20
+ RUBY_VERSION: '3.4.11'
21
+ BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/rails_8.0.gemfile
22
+ GEM_NAME: active_merchant_spgateway
23
+ GEMSPEC: active_merchant_spgateway.gemspec
24
+
25
+ jobs:
26
+ check:
27
+ name: Check version on rubygems.org
28
+ runs-on: ubuntu-latest
29
+ outputs:
30
+ should_publish: ${{ steps.check.outputs.should_publish }}
31
+ gem_name: ${{ steps.spec.outputs.name }}
32
+ gem_version: ${{ steps.spec.outputs.version }}
33
+ steps:
34
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
35
+ with:
36
+ persist-credentials: false
37
+
38
+ - uses: ruby/setup-ruby@b1da4809b005e0178fe08a1d57317bffc00b7b4c # v1.332.0
39
+ with:
40
+ ruby-version: ${{ env.RUBY_VERSION }}
41
+
42
+ - name: Read gem name and version from gemspec
43
+ id: spec
44
+ run: |
45
+ ruby -e 'spec = Gem::Specification.load(ENV.fetch("GEMSPEC")) or abort("cannot load #{ENV["GEMSPEC"]}"); abort("gemspec name #{spec.name} != #{ENV["GEM_NAME"]}") unless spec.name == ENV["GEM_NAME"]; puts "name=#{spec.name}"; puts "version=#{spec.version}"' >> "$GITHUB_OUTPUT"
46
+ cat "$GITHUB_OUTPUT"
47
+
48
+ - name: Check whether this version already exists on rubygems.org
49
+ id: check
50
+ env:
51
+ GEM_NAME: ${{ steps.spec.outputs.name }}
52
+ GEM_VERSION: ${{ steps.spec.outputs.version }}
53
+ run: |
54
+ set -euo pipefail
55
+ status=$(curl -sS -o versions.json -w '%{http_code}' "https://rubygems.org/api/v1/versions/${GEM_NAME}.json")
56
+ if [ "$status" = "404" ]; then
57
+ echo "Gem ${GEM_NAME} not found on rubygems.org; will publish."
58
+ echo "should_publish=true" >> "$GITHUB_OUTPUT"
59
+ exit 0
60
+ fi
61
+ if [ "$status" != "200" ]; then
62
+ echo "::error::rubygems.org API returned HTTP ${status}"
63
+ exit 1
64
+ fi
65
+ if jq -e --arg v "$GEM_VERSION" 'any(.[]; .number == $v)' versions.json > /dev/null; then
66
+ echo "${GEM_NAME} ${GEM_VERSION} already on rubygems.org; skip publish."
67
+ echo "should_publish=false" >> "$GITHUB_OUTPUT"
68
+ else
69
+ echo "${GEM_NAME} ${GEM_VERSION} not on rubygems.org yet; will publish."
70
+ echo "should_publish=true" >> "$GITHUB_OUTPUT"
71
+ fi
72
+
73
+ test:
74
+ name: Test (Ruby 3.4 / Rails 8.0)
75
+ needs: check
76
+ if: needs.check.outputs.should_publish == 'true'
77
+ runs-on: ubuntu-latest
78
+ steps:
79
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
80
+ with:
81
+ persist-credentials: false
82
+
83
+ - uses: ruby/setup-ruby@b1da4809b005e0178fe08a1d57317bffc00b7b4c # v1.332.0
84
+ with:
85
+ ruby-version: ${{ env.RUBY_VERSION }}
86
+ bundler-cache: true
87
+
88
+ - run: bundle exec rake t
89
+
90
+ publish:
91
+ name: Publish ${{ needs.check.outputs.gem_name }} ${{ needs.check.outputs.gem_version }}
92
+ needs: [check, test]
93
+ if: needs.check.outputs.should_publish == 'true' && github.ref == 'refs/heads/master'
94
+ runs-on: ubuntu-latest
95
+ environment: gem-publish
96
+ permissions:
97
+ id-token: write # Trusted Publishing (OIDC)
98
+ contents: write # rake release 推送 vX.Y.Z tag
99
+ steps:
100
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
101
+ with:
102
+ persist-credentials: false
103
+
104
+ - uses: ruby/setup-ruby@b1da4809b005e0178fe08a1d57317bffc00b7b4c # v1.332.0
105
+ with:
106
+ ruby-version: ${{ env.RUBY_VERSION }}
107
+ bundler-cache: true
108
+
109
+ # setup-ruby 的 bundler-cache 會把 BUNDLE_PATH 等設定寫進 .bundle/config,
110
+ # 若該檔被 git 追蹤,rake release 的 guard_clean 會判定工作目錄不乾淨。
111
+ # 目前此 repo 沒有追蹤任何 .bundle/config;這一步對「有追蹤才標記」做容錯處理,
112
+ # 日後若加入 gemfiles/.bundle/config 或 .bundle/config 也不會讓發佈失敗。
113
+ - name: Ignore CI-only bundler config change
114
+ run: |
115
+ git status --porcelain
116
+ git ls-files -z '*.bundle/config' | xargs -0 -r git update-index --assume-unchanged
117
+ git status --porcelain
118
+
119
+ # 透過 rubygems/configure-rubygems-credentials 取得短效 OIDC token,
120
+ # 再執行 bundle exec rake release(build、建立並推送 vX.Y.Z tag、push gem)
121
+ - uses: rubygems/release-gem@7f9650160c1a4e7989fdc9855807bdbd421d8b6b # v1.4.1
@@ -0,0 +1,47 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ pull_request:
7
+ branches: [ master ]
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ test:
14
+ name: Ruby ${{ matrix.ruby }} / Rails ${{ matrix.rails }}
15
+ runs-on: ubuntu-latest
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ ruby: ["3.0", "3.1", "3.2", "3.3", "3.4"]
20
+ rails: ["7.0", "7.1", "7.2", "8.0", "8.1"]
21
+ exclude:
22
+ # Rails 7.2 需要 Ruby >= 3.1
23
+ - ruby: "3.0"
24
+ rails: "7.2"
25
+ # Rails 8.0 / 8.1 需要 Ruby >= 3.2
26
+ - ruby: "3.0"
27
+ rails: "8.0"
28
+ - ruby: "3.0"
29
+ rails: "8.1"
30
+ - ruby: "3.1"
31
+ rails: "8.0"
32
+ - ruby: "3.1"
33
+ rails: "8.1"
34
+ env:
35
+ BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/rails_${{ matrix.rails }}.gemfile
36
+ steps:
37
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
38
+ with:
39
+ persist-credentials: false
40
+
41
+ - uses: ruby/setup-ruby@b1da4809b005e0178fe08a1d57317bffc00b7b4c # v1.332.0
42
+ with:
43
+ ruby-version: ${{ matrix.ruby }}
44
+ bundler-cache: true
45
+
46
+ - name: Run tests
47
+ run: bundle exec rake t
data/.gitignore CHANGED
@@ -10,3 +10,5 @@
10
10
  test/tmp/*
11
11
  *.gem
12
12
  coverage
13
+ /gemfiles/*.gemfile.lock
14
+ /gemfiles/.bundle/
data/CHANGELOG.md ADDED
@@ -0,0 +1,56 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ Release dates are the dates the version was published on [rubygems.org](https://rubygems.org/gems/active_merchant_spgateway).
9
+
10
+ ## [Unreleased]
11
+
12
+ > `lib/active_merchant_spgateway/version.rb` on `master` is already `0.1.0`, but that version is **not on rubygems.org yet**
13
+ > (the "Publish gem" run for it failed with "No trusted publisher configured for this workflow"), so it is listed here.
14
+ > Once 0.1.0 is published, rename this section to `## [0.1.0] - YYYY-MM-DD` and use the date shown on rubygems.org.
15
+
16
+ ### Added
17
+
18
+ - Support for Rails 7.0, 7.1, 7.2, 8.0 and 8.1 on Ruby 3.0 – 3.4. `actionview` and `activesupport` (`>= 7.0`, `< 8.2`) are now runtime dependencies.
19
+ - Unit tests (Minitest) for the form helper, the notification and the install generator; they never touch the network.
20
+ - GitHub Actions: a Ruby × Rails test matrix (`test.yml`) and automatic publishing to RubyGems through Trusted Publishing (`publish.yml`).
21
+ - `CHANGELOG.md`, a full `README.md`, and a documentation rule in `CLAUDE.md`.
22
+
23
+ ### Changed
24
+
25
+ - **Breaking:** requires Ruby `>= 3.0` (`required_ruby_version`); Rails older than 7.0 is no longer supported.
26
+ - Development dependencies (`bundler`, `rake`, `minitest`) were modernised; the old `rails < 5` development dependency was removed in favour of per-version `gemfiles/`.
27
+ - `README.md` installation instructions now use RubyGems instead of the old `github:` source.
28
+
29
+ ## [0.0.4] - 2023-03-15
30
+
31
+ ### Changed
32
+
33
+ - Point the payment gateway URLs to NewebPay's domain: `https://core.newebpay.com/MPG/mpg_gateway` (production) and `https://ccore.newebpay.com/MPG/mpg_gateway` (development / test), replacing `*.spgateway.com`.
34
+
35
+ ## [0.0.3] - 2018-11-16
36
+
37
+ Version `0.0.2` was never published to RubyGems, so its changes ship in this release.
38
+
39
+ ### Added
40
+
41
+ - Credit card agreement (約定信用卡授權) support: the `CREDITAGREEMENT` and `TokenLife` form fields, the `TokenValue` / `TokenLife` notification params, and `Notification#credit_card_agreement_first_trade?` and `Notification#credit_card_agreement_token_trade?`. (from 0.0.2)
42
+
43
+ ### Changed
44
+
45
+ - Require the `money` gem explicitly and tidy the gemspec metadata.
46
+
47
+ ## [0.0.1] - 2018-11-16
48
+
49
+ ### Added
50
+
51
+ - Initial release: ActiveMerchant / OffsitePayments integration for the Spgateway (智付通) MPG payment form, the `payment_service_for` helper, notification verification and a Rails install generator (`rails g spgateway:install`).
52
+
53
+ [Unreleased]: https://github.com/superlanding/active_merchant_spgateway/commits/master
54
+ [0.0.4]: https://rubygems.org/gems/active_merchant_spgateway/versions/0.0.4
55
+ [0.0.3]: https://rubygems.org/gems/active_merchant_spgateway/versions/0.0.3
56
+ [0.0.1]: https://rubygems.org/gems/active_merchant_spgateway/versions/0.0.1
data/CLAUDE.md ADDED
@@ -0,0 +1,20 @@
1
+ # CLAUDE.md
2
+
3
+ ## 發版規則(Ruby gem)
4
+
5
+ - 這個 gem(`active_merchant_spgateway`,gemspec:`active_merchant_spgateway.gemspec`)在 master 收到「新版本號」時,由 GitHub Actions(`.github/workflows/publish.yml`)自動發佈到 rubygems.org(Trusted Publishing,不使用 API key)。
6
+ - **每一個 PR 都必須跳版號**(改 `lib/active_merchant_spgateway/version.rb`),除非這個 PR 只改文件、CI 或 CLAUDE.md 且明確不需要發版。沒跳版號的 PR 合進 master 後不會發佈。
7
+ - 跳版規則(Semantic Versioning):修 bug 跳 patch(x.y.Z);新增相容功能跳 minor(x.Y.0);不相容變更跳 major(X.0.0)。
8
+ - 版號只改在 PR 裡。AI 帳號只能開 branch 與 PR,不得合併到 master;只有真人帳號可以合併。合併就等於批准發佈。
9
+ - 不得為了讓測試通過而改變程式原本的行為。
10
+
11
+ ## 文件與更新紀錄(README / CHANGELOG)
12
+
13
+ - **每一個 PR 都必須同步更新文件**:
14
+ - 只要行為、用法、設定、相依套件或支援的 Ruby / Rails 版本有變,就要更新 `README.md`。
15
+ - 一律要在 `CHANGELOG.md` 新增一筆條目([Keep a Changelog](https://keepachangelog.com/zh-TW/1.1.0/) 格式,分類用 Added / Changed / Deprecated / Removed / Fixed / Security)。
16
+ - `CHANGELOG.md` 的寫法:
17
+ - 沒有跳版號的 PR:寫在最上方的 `## [Unreleased]` 底下。
18
+ - 有跳版號的 PR:把條目寫在新的版本章節 `## [x.y.z] - YYYY-MM-DD`(日期為合併日),並同步更新檔尾的版本比較連結。
19
+ - 版本號必須與 rubygems.org 上實際發佈的版本一致,不得寫還沒發佈的版本。
20
+ - 只改文件、CI 或 CLAUDE.md 的 PR 不需要跳版號,但仍要在 `CHANGELOG.md` 的 `Unreleased` 補一筆。
data/README.md CHANGED
@@ -1,61 +1,101 @@
1
1
  # ActiveMerchantSpgateway
2
2
 
3
- This gem integrate Rails with [spgateway(智付通)](https://www.spgateway.com/).
3
+ [ActiveMerchant](https://github.com/activemerchant/active_merchant) / [OffsitePayments](https://github.com/activemerchant/offsite_payments) integration for **Spgateway (智付通, now NewebPay 藍新金流)** `MPG` (multi-payment gateway) for Rails. It lets a Rails app:
4
+
5
+ - render the hidden-field form that sends a customer to the Spgateway / NewebPay payment page (including the `CheckValue` signature), and
6
+ - parse and verify the server-to-server / return notification (`CheckCode`) Spgateway posts back.
7
+
8
+ The gem is published on [RubyGems](https://rubygems.org/gems/active_merchant_spgateway). See [CHANGELOG.md](CHANGELOG.md) for what changed in each version.
9
+
10
+ ## Requirements
11
+
12
+ | | Supported |
13
+ | --- | --- |
14
+ | Ruby | 3.0, 3.1, 3.2, 3.3, 3.4 |
15
+ | Rails (`actionview` / `activesupport`) | 7.0, 7.1, 7.2, 8.0, 8.1 |
16
+
17
+ Rails 7.2 needs Ruby >= 3.1, and Rails 8.0 / 8.1 need Ruby >= 3.2. These are exactly the combinations the CI matrix (`.github/workflows/test.yml`) runs. Other runtime dependencies: `activemerchant ~> 1.50`, `offsite_payments ~> 2`, `money`.
4
18
 
5
19
  ## Installation
6
20
 
7
- Add this line to your application's Gemfile:
21
+ Add this line to your application's `Gemfile`:
8
22
 
9
23
  ```ruby
10
- gem 'active_merchant_spgateway', github: 'afunction/active_merchant_spgateway'
24
+ gem 'active_merchant_spgateway', '>= 0.1.0'
11
25
  ```
12
26
 
13
- And then execute:
27
+ Then run:
14
28
 
15
- ```
16
- $ bundle
29
+ ```sh
30
+ bundle install
17
31
  ```
18
32
 
19
- ## Setup
33
+ > Support for Rails 7+ / Ruby 3+ is released as **0.1.0**. If 0.1.0 is not yet visible on RubyGems (check the [CHANGELOG](CHANGELOG.md)), use the Git source instead:
34
+ > `gem 'active_merchant_spgateway', github: 'superlanding/active_merchant_spgateway'`.
20
35
 
21
- - Create file `config/initializers/spgateway.rb`
22
- ``` sh
23
- rails g spgateway:install
24
- ```
36
+ ## Configuration
25
37
 
26
- - Go to spgateway and get your credential information. Then fill in `config/initializers/spgateway.rb`
27
- ```rb
28
- OffsitePayments::Integrations::Spgateway.setup do |spgateway|
29
- # You have to apply credential below by yourself.
30
- spgateway.merchant_id = '123456'
31
- spgateway.hash_key = 'xxx'
32
- spgateway.hash_iv = 'yyy'
33
- end
34
- ```
38
+ 1. Generate the initializer:
35
39
 
36
- - Environment configuration:
37
- ```rb
38
- # config/environments/development.rb
39
- config.after_initialize do
40
- ActiveMerchant::Billing::Base.mode = :development
41
- end
42
- ```
43
- ```rb
44
- # config/environments/production.rb
45
- config.after_initialize do
46
- ActiveMerchant::Billing::Base.mode = :production
47
- end
48
- ```
40
+ ```sh
41
+ rails g spgateway:install
42
+ ```
49
43
 
50
- ## Example
44
+ This creates `config/initializers/spgateway.rb`.
51
45
 
52
- - Standard
46
+ 2. Fill in the credentials you get from the Spgateway / NewebPay merchant back office:
53
47
 
54
- ```
55
- <% payment_service_for @order,
56
- @order.user.email,
57
- service: :spgateway,
58
- html: { :id => 'spgateway-form', :method => :post } do |service| %>
48
+ ```ruby
49
+ # config/initializers/spgateway.rb
50
+ OffsitePayments::Integrations::Spgateway.setup do |spgateway|
51
+ spgateway.merchant_id = '123456'
52
+ spgateway.hash_key = 'your 32-character HashKey'
53
+ spgateway.hash_iv = 'your 16-character HashIV'
54
+
55
+ # Optional defaults added to every form (all are optional):
56
+ # spgateway.notify_url = 'https://example.com/spgateway/notify'
57
+ # spgateway.lang_type = 'zh-tw' # LangType
58
+ # spgateway.login_type = 0 # LoginType
59
+ # spgateway.trade_limit = 600 # TradeLimit (seconds)
60
+ # spgateway.expire_date = 7 # ExpireDate (days)
61
+ # spgateway.email_modify = 1 # EmailModify
62
+ end
63
+ ```
64
+
65
+ Keep `hash_key` / `hash_iv` out of version control (Rails credentials or environment variables).
66
+
67
+ 3. Choose the environment. The gateway URL depends on `ActiveMerchant::Billing::Base.mode`:
68
+
69
+ | mode | URL |
70
+ | --- | --- |
71
+ | `:production` | `https://core.newebpay.com/MPG/mpg_gateway` |
72
+ | `:development` / `:test` | `https://ccore.newebpay.com/MPG/mpg_gateway` (sandbox) |
73
+
74
+ ```ruby
75
+ # config/environments/development.rb
76
+ config.after_initialize do
77
+ ActiveMerchant::Billing::Base.mode = :development
78
+ end
79
+ ```
80
+
81
+ ```ruby
82
+ # config/environments/production.rb
83
+ config.after_initialize do
84
+ ActiveMerchant::Billing::Base.mode = :production
85
+ end
86
+ ```
87
+
88
+ ## Usage
89
+
90
+ ### 1. Send the customer to the payment page
91
+
92
+ `payment_service_for` is available in views. Always call `service.encrypted_data` last; it computes `CheckValue` from `Amt`, `MerchantID`, `MerchantOrderNo`, `TimeStamp` and `Version`.
93
+
94
+ ```erb
95
+ <% payment_service_for @order,
96
+ @order.user.email,
97
+ service: :spgateway,
98
+ html: { id: 'spgateway-form', method: :post } do |service| %>
59
99
  <% service.time_stamp @order.created_at %>
60
100
  <% service.merchant_order_no @order.id %>
61
101
  <% service.amt @order.total_amount.to_i %>
@@ -63,17 +103,23 @@ end
63
103
  <% service.email @order.user.email %>
64
104
  <% service.login_type 0 %>
65
105
  <% service.encrypted_data %>
66
- <%= submit_tag '付款' %>
106
+ <%= submit_tag 'Pay' %>
67
107
  <% end %>
68
108
  ```
69
109
 
70
- - Credit card agreement
110
+ This renders a `<form method="post">` pointing at the gateway URL above with hidden inputs `MerchantID`, `Version` (`1.2`), `RespondType`, `TimeStamp`, `MerchantOrderNo`, `Amt`, `ItemDesc`, `Email`, `LoginType`, `CheckValue`, …
71
111
 
72
- ```
73
- <% payment_service_for @order,
74
- @order.user.email,
75
- service: :spgateway,
76
- html: { :id => 'spgateway-form', :method => :post } do |service| %>
112
+ Every Spgateway field has a snake_case setter: `merchant_id`, `lang_type`, `merchant_order_no`, `amt`, `item_desc`, `trade_limit`, `expire_date`, `return_url`, `notify_url`, `customer_url`, `client_back_url`, `email`, `email_modify`, `login_type`, `order_comment`, `credit`, `credit_red`, `inst_flag`, `unionpay`, `webatm`, `vacc`, `cvs`, `barcode`, `custom`, `token_term`, `creditagreement`, `token_life`. `account` and `amount` are aliases of `merchant_id` and `amt`.
113
+
114
+ To use a different HashKey / HashIV for one form (for example for multiple merchants), call `service.hash_key '...'` and `service.hash_iv '...'` before `service.encrypted_data`.
115
+
116
+ ### 2. Credit card agreement (約定信用卡授權)
117
+
118
+ Add `creditagreement` and `token_term` (your own unique member identifier):
119
+
120
+ ```erb
121
+ <% payment_service_for @order, @order.user.email, service: :spgateway,
122
+ html: { id: 'spgateway-form', method: :post } do |service| %>
77
123
  <% service.time_stamp @order.created_at %>
78
124
  <% service.merchant_order_no @order.id %>
79
125
  <% service.amt @order.total_amount.to_i %>
@@ -81,12 +127,69 @@ end
81
127
  <% service.email @order.user.email %>
82
128
  <% service.login_type 0 %>
83
129
  <% service.creditagreement 1 %>
84
- <% service.token_term billing.merchant_id %>
130
+ <% service.token_term @order.user.id.to_s %>
85
131
  <% service.encrypted_data %>
86
- <%= submit_tag '付款' %>
132
+ <%= submit_tag 'Pay' %>
87
133
  <% end %>
88
134
  ```
89
135
 
136
+ ### 3. Handle the notification
137
+
138
+ Point `notify_url` (and/or `return_url`) at a controller action, skip CSRF verification for it, and verify the signature before trusting the data:
139
+
140
+ ```ruby
141
+ class SpgatewayController < ApplicationController
142
+ skip_before_action :verify_authenticity_token, only: :notify
143
+
144
+ def notify
145
+ notification = OffsitePayments::Integrations::Spgateway.notification(request.raw_post)
146
+
147
+ if notification.checksum_ok? && notification.complete?
148
+ order = Order.find_by!(id: notification.merchant_order_no)
149
+ # notification.amt, notification.trade_no, notification.payment_type, notification.pay_time ...
150
+ order.mark_as_paid!(trade_no: notification.trade_no)
151
+ end
152
+
153
+ head :ok
154
+ end
155
+ end
156
+ ```
157
+
158
+ Available helpers on the notification:
159
+
160
+ - `checksum_ok?` / `acknowledge` — verifies `CheckCode` (SHA256 of `Amt`, `MerchantID`, `MerchantOrderNo`, `TradeNo` with your `HashIV` / `HashKey`). Spgateway has no remote verification, so this is the only authenticity check; **always call it**.
161
+ - `success?` — `Status == 'SUCCESS'`; `complete?` — `Status` is `SUCCESS` or `CUSTOM`.
162
+ - Raw fields as snake_case readers: `status`, `message`, `merchant_id`, `amt`, `trade_no`, `merchant_order_no`, `payment_type`, `pay_time`, `check_code`, `card6_no`, `card4_no`, `pay_bank_code`, `code_no`, `bank_code`, `barcode_1` … (see `PARAMS_FIELDS` in `notification.rb`). Note the base class method `gross` is **not** implemented; use `amt`.
163
+ - `credit_card_agreement_first_trade?` — first transaction of a credit card agreement (`TokenUseStatus == '1'`); `credit_card_agreement_token_trade?` — a later token transaction. The `token_value` and `token_life` readers carry the token data.
164
+ - To verify with a per-merchant key, set `notification.hash_key = '...'` and `notification.hash_iv = '...'` before `checksum_ok?`.
165
+
166
+ ## Development
167
+
168
+ ```sh
169
+ git clone https://github.com/superlanding/active_merchant_spgateway.git
170
+ cd active_merchant_spgateway
171
+ BUNDLE_GEMFILE=gemfiles/rails_8.1.gemfile bundle install
172
+ BUNDLE_GEMFILE=gemfiles/rails_8.1.gemfile bundle exec rake t # alias of `rake test:units`
173
+ ```
174
+
175
+ Pick any gemfile in `gemfiles/` (`rails_7.0` … `rails_8.1`) that matches your Ruby version. The tests are plain Minitest, live in `test/unit/`, and block all network access (any `Net::HTTP` connection raises). Set `COVERAGE=1` to run SimpleCov.
176
+
177
+ CI (`.github/workflows/test.yml`) runs the whole Ruby × Rails matrix for every PR and push to `master`.
178
+
179
+ ## Releasing
180
+
181
+ Releases are automatic (RubyGems [Trusted Publishing](https://guides.rubygems.org/trusted-publishing/), no API key stored):
182
+
183
+ 1. In your PR, bump `ActiveMerchantSpgateway::VERSION` in `lib/active_merchant_spgateway/version.rb` (SemVer) and move the `## [Unreleased]` entries in `CHANGELOG.md` under a new `## [x.y.z] - YYYY-MM-DD` section.
184
+ 2. Merge the PR into `master`.
185
+ 3. `.github/workflows/publish.yml` sees that the version is not on rubygems.org yet, builds the gem and runs `rake release`, which publishes it and creates the `vx.y.z` git tag. If the version already exists, the workflow does nothing.
186
+
187
+ PRs that do not bump the version (docs, CI, refactors) are never published.
188
+
189
+ ## Contributing
190
+
191
+ Bug reports and pull requests are welcome on GitHub at https://github.com/superlanding/active_merchant_spgateway. Every pull request must also update this README (when behaviour, usage or requirements change) and add an entry to `CHANGELOG.md`; see `CLAUDE.md`.
192
+
90
193
  ## License
91
194
 
92
- The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
195
+ The gem is available as open source under the terms of the [MIT License](LICENSE.txt).
data/Rakefile CHANGED
@@ -6,12 +6,12 @@ desc "Run the unit test suite"
6
6
  task :default => 'test:units'
7
7
 
8
8
  task :test => 'test:units'
9
+ task :t => 'test:units'
9
10
 
10
11
  namespace :test do
11
12
 
12
13
  Rake::TestTask.new(:units) do |t|
13
14
  t.pattern = 'test/unit/**/*_test.rb'
14
- t.ruby_opts << '-rubygems'
15
15
  t.libs << 'test'
16
16
  t.verbose = true
17
17
  end
@@ -14,6 +14,8 @@ Gem::Specification.new do |spec|
14
14
  spec.homepage = "https://github.com/superlanding/active_merchant_spgateway"
15
15
  spec.license = "MIT"
16
16
 
17
+ spec.required_ruby_version = ">= 3.0"
18
+
17
19
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
20
  spec.bindir = "exe"
19
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
@@ -23,8 +25,11 @@ Gem::Specification.new do |spec|
23
25
  spec.add_dependency 'money'
24
26
  spec.add_dependency 'offsite_payments', '~> 2'
25
27
 
26
- spec.add_development_dependency 'bundler', '~> 1.10'
27
- spec.add_development_dependency 'rake', '~> 10.0'
28
- spec.add_development_dependency 'rails', '>= 3.2.6', '< 5'
28
+ spec.add_dependency 'actionview', '>= 7.0', '< 8.2'
29
+ spec.add_dependency 'activesupport', '>= 7.0', '< 8.2'
30
+
31
+ spec.add_development_dependency 'bundler', '>= 2.0'
32
+ spec.add_development_dependency 'rake', '>= 13'
33
+ spec.add_development_dependency 'minitest', '~> 5.0'
29
34
 
30
35
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ source "https://rubygems.org"
3
+
4
+ gemspec path: ".."
5
+
6
+ gem "rails", "~> 7.0.0"
7
+ gem "rake", ">= 13"
8
+ gem "minitest", "~> 5.0"
9
+ gem "minitest-reporters", require: false
10
+ gem "simplecov", require: false
11
+
12
+ # concurrent-ruby 1.3.5 起不再自動 require logger,Rails 7.0 / 7.1 會載入失敗
13
+ gem "concurrent-ruby", "< 1.3.5"
14
+
15
+ # Ruby 3.4 已不再內建這些 gem;Rails 7.0 / 7.1 沒有自行宣告,故明確列出
16
+ gem "logger"
17
+ gem "mutex_m"
18
+ gem "bigdecimal"
19
+ gem "base64"
20
+ gem "drb"
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ source "https://rubygems.org"
3
+
4
+ gemspec path: ".."
5
+
6
+ gem "rails", "~> 7.1.0"
7
+ gem "rake", ">= 13"
8
+ gem "minitest", "~> 5.0"
9
+ gem "minitest-reporters", require: false
10
+ gem "simplecov", require: false
11
+
12
+ # concurrent-ruby 1.3.5 起不再自動 require logger,Rails 7.0 / 7.1 會載入失敗
13
+ gem "concurrent-ruby", "< 1.3.5"
14
+
15
+ # Ruby 3.4 已不再內建這些 gem;Rails 7.0 / 7.1 沒有自行宣告,故明確列出
16
+ gem "logger"
17
+ gem "mutex_m"
18
+ gem "bigdecimal"
19
+ gem "base64"
20
+ gem "drb"
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+ source "https://rubygems.org"
3
+
4
+ gemspec path: ".."
5
+
6
+ gem "rails", "~> 7.2.0"
7
+ gem "rake", ">= 13"
8
+ gem "minitest", "~> 5.0"
9
+ gem "minitest-reporters", require: false
10
+ gem "simplecov", require: false
11
+
12
+ # Ruby 3.4 已不再內建這些 gem;Rails 7.0 / 7.1 沒有自行宣告,故明確列出
13
+ gem "logger"
14
+ gem "mutex_m"
15
+ gem "bigdecimal"
16
+ gem "base64"
17
+ gem "drb"
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+ source "https://rubygems.org"
3
+
4
+ gemspec path: ".."
5
+
6
+ gem "rails", "~> 8.0.0"
7
+ gem "rake", ">= 13"
8
+ gem "minitest", "~> 5.0"
9
+ gem "minitest-reporters", require: false
10
+ gem "simplecov", require: false
11
+
12
+ # Ruby 3.4 已不再內建這些 gem;Rails 7.0 / 7.1 沒有自行宣告,故明確列出
13
+ gem "logger"
14
+ gem "mutex_m"
15
+ gem "bigdecimal"
16
+ gem "base64"
17
+ gem "drb"
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+ source "https://rubygems.org"
3
+
4
+ gemspec path: ".."
5
+
6
+ gem "rails", "~> 8.1.0"
7
+ gem "rake", ">= 13"
8
+ gem "minitest", "~> 5.0"
9
+ gem "minitest-reporters", require: false
10
+ gem "simplecov", require: false
11
+
12
+ # Ruby 3.4 已不再內建這些 gem;Rails 7.0 / 7.1 沒有自行宣告,故明確列出
13
+ gem "logger"
14
+ gem "mutex_m"
15
+ gem "bigdecimal"
16
+ gem "base64"
17
+ gem "drb"
@@ -1,3 +1,3 @@
1
1
  module ActiveMerchantSpgateway
2
- VERSION = "0.0.3"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -29,11 +29,11 @@ module OffsitePayments #:nodoc:
29
29
  mode = ActiveMerchant::Billing::Base.mode
30
30
  case mode
31
31
  when :production
32
- 'https://core.spgateway.com/MPG/mpg_gateway'
32
+ 'https://core.newebpay.com/MPG/mpg_gateway'
33
33
  when :development
34
- 'https://ccore.spgateway.com/MPG/mpg_gateway'
34
+ 'https://ccore.newebpay.com/MPG/mpg_gateway'
35
35
  when :test
36
- 'https://ccore.spgateway.com/MPG/mpg_gateway'
36
+ 'https://ccore.newebpay.com/MPG/mpg_gateway'
37
37
  else
38
38
  raise StandardError, "Integration mode set to an invalid value: #{mode}"
39
39
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_merchant_spgateway
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eddie Li
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2018-11-16 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activemerchant
@@ -53,53 +52,87 @@ dependencies:
53
52
  - !ruby/object:Gem::Version
54
53
  version: '2'
55
54
  - !ruby/object:Gem::Dependency
56
- name: bundler
55
+ name: actionview
57
56
  requirement: !ruby/object:Gem::Requirement
58
57
  requirements:
59
- - - "~>"
58
+ - - ">="
60
59
  - !ruby/object:Gem::Version
61
- version: '1.10'
62
- type: :development
60
+ version: '7.0'
61
+ - - "<"
62
+ - !ruby/object:Gem::Version
63
+ version: '8.2'
64
+ type: :runtime
63
65
  prerelease: false
64
66
  version_requirements: !ruby/object:Gem::Requirement
65
67
  requirements:
66
- - - "~>"
68
+ - - ">="
67
69
  - !ruby/object:Gem::Version
68
- version: '1.10'
70
+ version: '7.0'
71
+ - - "<"
72
+ - !ruby/object:Gem::Version
73
+ version: '8.2'
69
74
  - !ruby/object:Gem::Dependency
70
- name: rake
75
+ name: activesupport
71
76
  requirement: !ruby/object:Gem::Requirement
72
77
  requirements:
73
- - - "~>"
78
+ - - ">="
74
79
  - !ruby/object:Gem::Version
75
- version: '10.0'
76
- type: :development
80
+ version: '7.0'
81
+ - - "<"
82
+ - !ruby/object:Gem::Version
83
+ version: '8.2'
84
+ type: :runtime
77
85
  prerelease: false
78
86
  version_requirements: !ruby/object:Gem::Requirement
79
87
  requirements:
80
- - - "~>"
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '7.0'
91
+ - - "<"
81
92
  - !ruby/object:Gem::Version
82
- version: '10.0'
93
+ version: '8.2'
83
94
  - !ruby/object:Gem::Dependency
84
- name: rails
95
+ name: bundler
85
96
  requirement: !ruby/object:Gem::Requirement
86
97
  requirements:
87
98
  - - ">="
88
99
  - !ruby/object:Gem::Version
89
- version: 3.2.6
90
- - - "<"
100
+ version: '2.0'
101
+ type: :development
102
+ prerelease: false
103
+ version_requirements: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '2.0'
108
+ - !ruby/object:Gem::Dependency
109
+ name: rake
110
+ requirement: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
91
113
  - !ruby/object:Gem::Version
92
- version: '5'
114
+ version: '13'
93
115
  type: :development
94
116
  prerelease: false
95
117
  version_requirements: !ruby/object:Gem::Requirement
96
118
  requirements:
97
119
  - - ">="
98
120
  - !ruby/object:Gem::Version
99
- version: 3.2.6
100
- - - "<"
121
+ version: '13'
122
+ - !ruby/object:Gem::Dependency
123
+ name: minitest
124
+ requirement: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - "~>"
101
127
  - !ruby/object:Gem::Version
102
- version: '5'
128
+ version: '5.0'
129
+ type: :development
130
+ prerelease: false
131
+ version_requirements: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - "~>"
134
+ - !ruby/object:Gem::Version
135
+ version: '5.0'
103
136
  description: This gem integrate Rails with spgateway (智付通).
104
137
  email:
105
138
  - eddie@super-landing.com
@@ -107,8 +140,12 @@ executables: []
107
140
  extensions: []
108
141
  extra_rdoc_files: []
109
142
  files:
143
+ - ".github/workflows/publish.yml"
144
+ - ".github/workflows/test.yml"
110
145
  - ".gitignore"
111
146
  - ".travis.yml"
147
+ - CHANGELOG.md
148
+ - CLAUDE.md
112
149
  - CODE_OF_CONDUCT.md
113
150
  - Gemfile
114
151
  - LICENSE.txt
@@ -117,6 +154,11 @@ files:
117
154
  - active_merchant_spgateway.gemspec
118
155
  - bin/console
119
156
  - bin/setup
157
+ - gemfiles/rails_7.0.gemfile
158
+ - gemfiles/rails_7.1.gemfile
159
+ - gemfiles/rails_7.2.gemfile
160
+ - gemfiles/rails_8.0.gemfile
161
+ - gemfiles/rails_8.1.gemfile
120
162
  - lib/active_merchant_spgateway.rb
121
163
  - lib/active_merchant_spgateway/version.rb
122
164
  - lib/generators/spgateway/install_generator.rb
@@ -129,7 +171,6 @@ homepage: https://github.com/superlanding/active_merchant_spgateway
129
171
  licenses:
130
172
  - MIT
131
173
  metadata: {}
132
- post_install_message:
133
174
  rdoc_options: []
134
175
  require_paths:
135
176
  - lib
@@ -137,16 +178,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
137
178
  requirements:
138
179
  - - ">="
139
180
  - !ruby/object:Gem::Version
140
- version: '0'
181
+ version: '3.0'
141
182
  required_rubygems_version: !ruby/object:Gem::Requirement
142
183
  requirements:
143
184
  - - ">="
144
185
  - !ruby/object:Gem::Version
145
186
  version: '0'
146
187
  requirements: []
147
- rubyforge_project:
148
- rubygems_version: 2.4.8
149
- signing_key:
188
+ rubygems_version: 3.6.9
150
189
  specification_version: 4
151
190
  summary: ActiveMerchant x spgateway (智付通)
152
191
  test_files: []