paygate-ruby
is a simple Ruby wrapper for PayGate Korean payment gateway's OpenPayAPI.
Add this line to your application's Gemfile:
gem 'paygate-ruby'
You can pass a block to the configure
method to make changes to the Paygate
configuration.
Paygate.configure do |config|
config.mode = :sandbox
end
Default value for mode
is :live
. It uses different API urls in different modes for making payments.
To start making the transactions on PayGate, you will need a Member ID and a Secret, for which you can register here.
After a successful registration, you will have access to the dashboard.
NOTE: Unless otherwise stated, all the following documentation is for making payments with Korean local credit cards in currency 'WON'.
Contents:
Add Paygate::Rails::FormHelper
to your controller.
class ApplicationController < ActionController::Base
include Paygate::Rails::FormHelper
Then include the OpenPayAPI.js file in <head>
of your payment page.
<%= javascript_include_tag paygate_open_pay_api_js_url %>
Render the PayGate payment form in your view file.
<%= paygate_open_pay_api_form %>
You will see a form with all the necessary fields for making payment with a credit card. Some of the fields have default values set. You can also set the value and placeholder for almost all the fields while rendering the form. See example below:
<%= paygate_open_pay_api_form(
mid: { value: 'testmid', placeholder: 'Merchant ID' },
currency: { value: 'USD' },
amount: { value: 2000 }
) %>
Here is a list of all the form fields which you can set:
- mid
- locale (default: 'US')
- charset (default: 'UTF-8')
- title
- currency (default: 'WON')
- amount
- meta1, meta2, meta3, meta4, meta5
- pay_method (default: 'card')
- customer_name
- customer_email
- card_number
- expiry_year
- expiry_month
- cvv
The form also contains some fields which are filled after the response is returned by the API. They are:
- card_auth_code
- response_code
- response_message
- tid
- profile_no
- hash_result
Lets explore some of these fields more.
mid
You need to set your Member ID in this field.
If you have setup separate Member IDs for Korean and International cards, you can fill the value of mid
accordingly. To know whether the credit card number entered by a customer is Korean or not, you can check the first 6 digits of card number to match Korean BIN numbers. Full list is available as Paygate::KOREA_BIN_NUMBERS
.
pay_method
Value of pay_method
for Korean cards should be set to "card" and for international cards, it should be "104".
locale
Use Paygate.mapped_locale
to get the locale in correct format for the form input.
Paygate.mapped_locale(:en)
#=> 'US'
Paygate.mapped_locale('ko')
#=> 'KR'
Valid inputs are "en", "en-US", "ko", "ko-KR", "ja", "zh-CN" and their symbolized versions. Passing nil
would return default locale i.e. "US".
currency
Use Paygate.mapped_currency
to get the currency in the correct format.
Paygate.mapped_currency('USD')
#=> 'USD'
Paygate.mapped_currency('KRW')
#=> 'WON'
Passing nil
above would return default currency i.e. "WON".
amount
You need to contact PayGate to know the correct amount for making a successful transaction in test mode.
Remember, in test mode too, PayGate makes real transactions and you need to refund
them.
meta1, meta2, meta3, meta4, meta5
These fields can be used to pass any additional data to PayGate. If server-to-server callbacks are enabled, the gateway then sends all of these back when making a callback request to your server.
tid
For every transaction a tid
is created by PayGate JS before making a request to the API.
response_code
This is filled automatically by PayGate JS when response is returned. A response_code
of "0000" means successful transaction.
response_message
In case of failure, you can see the error message returned by the API here.
profile_no
If Profile Payment Service is enabled on your Member ID, then you will get a subscription ID for customer in this field. You can use this profile_no
to make payments for the same customer in future.
You also need to add a screen at the same HTML level as above form. OpenPayAPI popups for further authentication as well as the response from the API is displayed in this screen.
= paygate_open_pay_api_screen
You also need to implement a few callbacks to handle the API response. Add these to your JavaScript.
// This is called when a response is returned from PayGate API
function getPGIOresult() {
displayStatus(getPGIOElement('ResultScreen'));
verifyReceived(getPGIOElement('tid'), 'callbacksuccess', 'callbackfail');
}
// This is called when a response (success/failure) is returned from the API
function callbacksuccess() {
var replycode = getPGIOElement('replycode');
if (replycode == '0000') {
alert('Payment was successful');
} else {
alert('Payment failed with code: ' + replycode);
}
}
// This is called when there is a system error
function callbackfail() {
alert('System error. Please try again.');
}
Now finally, lets add an event to make a call to OpenPayAPI on submit of the form. If you are using jQuery, you can do it as follows:
$('form[name="PGIOForm"]').on('submit', function(event){
event.preventDefault();
doTransaction(document.PGIOForm);
})
And, your payment form is all set to make payments.
If enabled, PayGate will send a server-to-server callback on every successful transaction to the URL provided by you. The same request is sent every 5 minutes (for 10 days) until your server responds with success.
This feature can be helpful if your JavaScript failed to receive the message from PayGate after a successful payment due to network issues.
So, once you receive a successful JavaScript callback (replycode == '0000'
), to prevent PayGate from sending any callback requests for that transaction (tid
), you need to make a verification request as follows:
txn = Paygate::Transaction.new('testmid_123456.654321')
response = txn.verify
#=> #<Paygate::Response:0x007fd4898f14b0 ... >
response.transaction_type
#=> :verify
response.http_code
#=> "200"
Here, testmid_123456.654321 is tid
of the transaction you want to verify.
Initialize a Paygate::Member
instance using the Member ID and Secret you have.
member = Paygate::Member.new('testmid', 'secret')
#=> #<Paygate::Member:0x007f96bdb70f38 @mid="testmid", @secret="secret">
member
responds to methods mid
, and secret
.
member.mid
#=> "testmid"
member.secret
#=> "secret"
response = member.refund_transaction('testmid_123456.654321')
#=> #<Paygate::Response:0x007fbf3d111940 @transaction_type=:refund, @http_code="200", @message="OK", @body="callback({\"replyCode\":\"0000\",\"replyMessage\":\"Response has been completed\",\"content\":{\"object\":\"CancelAPI tid:testmid_123456.654321 SUCCESS payRsltCode:0000\"}})", @json={"replyCode"=>"0000", "replyMessage"=>"Response has been completed", "content"=>{"object"=>"CancelAPI tid:testmid_123456.654321 SUCCESS payRsltCode:0000"}}, @raw_info=
#<OpenStruct tid="testmid_123456.654321", tid_enc="AES256XQIdNnkzFwMQmhF7fuJhS3m0\n", request_url="https://service.paygate.net/service/cancelAPI.json?callback=callback&mid=testmid&tid=AES256XQIdNnkzFwMQmhF7fuJhS3m0%0A&amount=F">>
response
provides some helpful accessor methods too.
response.transaction_type
#=> :refund
response.http_code
#=> "200"
response.json
#=> {"replyCode"=>"0000", "replyMessage"=>"Response has been completed", "content"=>{"object"=>"CancelAPI tid:testmid_123456.654321 SUCCESS payRsltCode:0000"}}
response.raw_info
#=> #<OpenStruct tid="testmid_123456.654321", tid_enc="AES256XQIdNnkzFwMQmhF7fuJhS3m0\n", request_url="https://service.paygate.net/service/cancelAPI.json?callback=callback&mid=testmid&tid=AES256XQIdNnkzFwMQmhF7fuJhS3m0%0A&amount=F">
response.raw_info.request_url
#=> "https://service.paygate.net/service/cancelAPI.json?callback=callback&mid=testmid&tid=AES256XQIdNnkzFwMQmhF7fuJhS3m0%0A&amount=F"
Apart from these it also responds to message
and body
.
For partial refunds, you need to pass amount
as an option to refund_transaction
method along with other options.
response = member.refund_transaction('testmid_123456.654321',
amount: 1000,
order_id: 'ord10001')
You can use the profile_no
returned from the OpenPayAPI after first payment by a customer to make future payments for him.
response = member.profile_pay('profile_1234567890', 'WON', 1000)
response.transaction_type
#=> :profile_pay
response.http_code
#=> "200"
response.json
#=> {"validecode"=>"00", "authcode"=>"12345678", "authdt"=>"20171120165728", "cardname"=>"BC \x00\x00\x00\x00", "cardnumber"=>"411111**********", "cardtype"=>"301310", "cardquota"=>"00", "cardexpiremonth"=>"11", "cardexpireyear"=>"2020", "merchantno"=>"12345678", "m_tid"=>nil, "paymethodname"=>"CARD_BASIC", "ReplyMsg"=>"\xBA\xBA\xBC\xBD\xC1\xC2\xC3\xC4 OK: 12345678", "ReplyCode"=>"0000", "receipttoname"=>"Test name\xC1\xD1\xB1\xB1\xC1\xA1", "receipttoemail"=>"[email protected]", "subtotalprice"=>"1000", "transactionid"=>"testmid_123456.654321", "hashresult"=>"db1fdc6789cc8d088172b79ca680b3af8711e9fb32", "mb_serial_no"=>"\r\n"}
paygate-ruby
also provides a JavaScript class Paygate
with some helper functions that can be used in your JavaScript e.g.
- openPayApiForm - Returns the payment form
- openPayApiScreen - Returns the screen for paygate API response
- findInputByName - Find an input field in payment form by name. Pass the camelCased form of field names from section 1.2 above as arguments.
- responseCode
- responseMessage
- tid
- profileNo
- fillInput - Accepts input name (camelCased) and a value to set
- submitForm - Makes a call to PayGate API with the payment form inputs
Bug reports and pull requests are welcome on GitHub at https://github.com/tablecheck/paygate-ruby.