Skip to content

Instantly share code, notes, and snippets.

@Oschangkai
Last active July 1, 2024 05:35
Show Gist options
  • Save Oschangkai/b5f92effe5d3583e95b906e1686c2beb to your computer and use it in GitHub Desktop.
Save Oschangkai/b5f92effe5d3583e95b906e1686c2beb to your computer and use it in GitHub Desktop.
JCB ezcard
// ==UserScript==
// @name ezcard-helper
// @namespace http://tampermonkey.net/
// @version 2024.07.01
// @description 懂的都懂
// @author Oschangkai
// @match https://ezweb.easycard.com.tw/Event01/JCBLoginServlet
// @match https://ezweb.easycard.com.tw/Event01/JCBLoginRecordServlet
// @grant none
// ==/UserScript==
(function () {
"use strict";
// default buttons, all you need to do is to modify the default ones
let buttons = [
{
text: "測試卡 1",
txtCreditCard1: "1111",
txtCreditCard2: "22",
txtCreditCard4: "3333",
txtEasyCard1: "4444",
txtEasyCard2: "5555",
txtEasyCard3: "6666",
txtEasyCard4: "7777",
},
{
text: "測試卡 2",
txtCreditCard1: "8888",
txtCreditCard2: "99",
txtCreditCard4: "0000",
txtEasyCard1: "1111",
txtEasyCard2: "2222",
txtEasyCard3: "3333",
txtEasyCard4: "4444",
},
];
// if injector is working, replace buttons with data from injector
const injector = document.documentElement.getElementsByTagName("jcb-injector");
if (injector && injector.length) {
let data = injector[0].getAttribute("cards");
if (!!data && !!data.length) {
buttons = JSON.parse(data);
}
}
/** handle custom recaptcha elements */
function recaptchaLoader() {
// preconnect to google
const googleLink = document.createElement("link");
googleLink.rel = "preconnect";
googleLink.href = "https://www.google.com";
document.head.appendChild(googleLink);
// preconnect to gstatic
const gstaticLink = document.createElement("link");
gstaticLink.rel = "preconnect";
gstaticLink.href = "https://www.gstatic.com";
gstaticLink.crossorigin = true;
document.head.appendChild(gstaticLink);
// create recaptcha container
let recaptchaContainer = document.createElement("div");
recaptchaContainer.style.position = "fixed";
recaptchaContainer.style.bottom = "10px";
recaptchaContainer.style.left = "35px";
recaptchaContainer.style.zIndex = "9999";
recaptchaContainer.id = "recaptcha";
recaptchaContainer.className = "g-recaptcha";
document.documentElement.appendChild(recaptchaContainer);
// create recaptcha script
const recaptchaScript = document.createElement("script");
recaptchaScript.src = "https://www.google.com/recaptcha/api.js?onload=recaptchaOnload&render=explicit";
document.head.appendChild(recaptchaScript);
function recaptchaCallback(token) {
if (!!document.documentElement.getElementsByTagName("g-recaptcha-response").length) {
document.documentElement.getElementsByTagName("g-recaptcha-response")[0].textContent = token;
return;
}
let recaptchaTokenContainer = document.createElement("g-recaptcha-response");
recaptchaTokenContainer.textContent = token;
document.documentElement.appendChild(recaptchaTokenContainer);
}
window.recaptchaCallback = recaptchaCallback;
function recaptchaExpired() {
let recaptchaTokenContainer = document.documentElement.getElementsByTagName("g-recaptcha-response");
recaptchaTokenContainer[0].textContent = "";
}
window.recaptchaExpired = recaptchaExpired;
function recaptchaOnload() {
grecaptcha.render("recaptcha", {
sitekey: "6LfhNyoUAAAAACy6h4y3FRqxuMYhS6RXPcVlGenJ",
theme: "light",
size: "compact",
callback: recaptchaCallback,
"expired-callback": recaptchaExpired,
});
}
window.recaptchaOnload = recaptchaOnload;
}
recaptchaLoader();
/** create submit button and buttons which can be clicked to fill in card number */
function createButtons() {
buttons.forEach(function (btn, index) {
// create element
let button = document.createElement("button");
button.innerHTML = btn.text;
// style
button.style.position = "fixed";
button.style.bottom = 10 + index * 37 + "px"; // 調整每個按鈕的位置
button.style.right = "35px";
button.style.zIndex = "9999";
let elements = {
accept: !!document.getElementById("accept"),
txtCreditCard1: !!document.getElementById("txtCreditCard1"),
txtCreditCard2: !!document.getElementById("txtCreditCard2"),
txtCreditCard3: !!document.getElementById("txtCreditCard3"),
txtCreditCard4: !!document.getElementById("txtCreditCard4"),
txtEasyCard1: !!document.getElementById("txtEasyCard1"),
txtEasyCard2: !!document.getElementById("txtEasyCard2"),
txtEasyCard3: !!document.getElementById("txtEasyCard3"),
txtEasyCard4: !!document.getElementById("txtEasyCard4"),
};
button.onclick = function () {
// check recaptcha token
const recaptchaTokenContainer = document.documentElement.getElementsByTagName("g-recaptcha-response");
// if custom recaptcha is not ready, fill in the form directly
if (!recaptchaTokenContainer || !recaptchaTokenContainer.length || recaptchaTokenContainer[0].textContent === "") {
for (const key in elements) {
if (!elements[key]) {
continue;
}
if (key === "accept") {
document.getElementById(key).click();
} else {
document.getElementById(key).value = buttons[index][key];
}
}
return;
}
// build general form data
let postData = {
"g-recaptcha-response": recaptchaTokenContainer[0].textContent,
txtEasyCard1: btn.txtEasyCard1,
txtEasyCard2: btn.txtEasyCard2,
txtEasyCard3: btn.txtEasyCard3,
txtEasyCard4: btn.txtEasyCard4,
};
// JCBLoginServlet => login form, JCBLoginRecordServlet => query form
const action = window.location.pathname.split("/")[2];
if (action === "JCBLoginServlet") {
postData.txtCreditCard1 = btn.txtCreditCard1;
postData.txtCreditCard2 = btn.txtCreditCard2;
postData.txtCreditCard4 = btn.txtCreditCard4;
postData.accept = "";
postData.method = "loginAccept";
} else if (action === "JCBLoginRecordServlet") {
postData.method = "queryLoginDate";
}
// build form
const form = document.createElement("form");
form.setAttribute("method", "post");
form.setAttribute("action", action);
for (const key in postData) {
if (postData.hasOwnProperty(key)) {
const hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", postData[key]);
form.appendChild(hiddenField);
}
}
document.documentElement.appendChild(form);
form.submit();
};
// show buttons on page
document.documentElement.appendChild(button);
});
}
/** modify message, show card name before card number */
function showCardNameBeforeCardNumber() {
// find message on page
let message = document.querySelector(".success") || document.querySelector(".card_num");
// modify message on page
if (message) {
let card = message.textContent.match(/(\d{16})/);
if (card) {
let cardNumber = card[1];
let foundCard = buttons.find(function (card) {
let easyCardNumber = card.txtEasyCard1 + card.txtEasyCard2 + card.txtEasyCard3 + card.txtEasyCard4;
return easyCardNumber === cardNumber;
});
if (foundCard) {
message.innerHTML = message.innerHTML.replace(cardNumber, foundCard.text + " - " + cardNumber);
}
}
}
}
createButtons();
showCardNameBeforeCardNumber();
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment