Skip to content

Commit

Permalink
Merge pull request #3 from Chapa-Et/main
Browse files Browse the repository at this point in the history
merge validation and fix PRs
  • Loading branch information
isrugeek authored Aug 29, 2024
2 parents 8c02530 + f513b71 commit 84dffe1
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 45 deletions.
Binary file modified docs/inline-custom.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/inline-ecom-checkout.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
121 changes: 76 additions & 45 deletions lib/inline.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class ChapaCheckout {
onClose: options.onClose || null,
};

this.paymentType = "";
this.paymentType = this.options.availablePaymentMethods[0] ?? '';
this.hostedUrl = "https://api.chapa.co/v1/hosted/pay";
this.chapaUrl = "https://inline.chapaservices.net/v1/inline/charge";
this.verifyUrl = "https://inline.chapaservices.net/v1/inline/validate";
Expand Down Expand Up @@ -66,8 +66,8 @@ class ChapaCheckout {
}

container.innerHTML = `
<div id="chapa-error-container" class="chapa-error"></div>
<div id="chapa-phone-input-container"></div>
<div id="chapa-error-container" class="chapa-error"></div>
<div id="chapa-payment-methods"></div>
<button id="chapa-pay-button" type="submit"></button>
<div id="chapa-loading-container" class="chapa-loading">
Expand All @@ -81,6 +81,18 @@ class ChapaCheckout {
this.renderPayButton();
this.applyCustomStyles();
}

validatePhoneNumberOnInput(e) {
const phoneNumber = e.target.value;
const mobileRegex = /^(251\d{9}|0\d{9}|9\d{8}|7\d{8})$/;
if (!mobileRegex.test(phoneNumber)) {
this.showError("Please enter a valid Ethiopian phone number.");
return false;
}else{
this.hideError();
}
return true;
}

renderPhoneInput() {
const inputContainer = document.getElementById(
Expand All @@ -102,21 +114,40 @@ class ChapaCheckout {
<span>+251</span>
</div>`
}
<input type="tel" id="chapa-phone-number" name="mobile" value="${
this.options.mobile || ""
}" placeholder="9|7xxxxxxxx" required class="chapa-phone-input">
<div id="phone-input-container"></div>
<svg width="24px" height="24px" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg" id="secure">
<path
d="M19.42,3.83,12.24,2h0A.67.67,0,0,0,12,2a.67.67,0,0,0-.2,0h0L4.58,3.83A2,2,0,0,0,3.07,5.92l.42,5.51a12,12,0,0,0,7.24,10.11l.88.38h0a.91.91,0,0,0,.7,0h0l.88-.38a12,12,0,0,0,7.24-10.11l.42-5.51A2,2,0,0,0,19.42,3.83ZM15.71,9.71l-4,4a1,1,0,0,1-1.42,0l-2-2a1,1,0,0,1,1.42-1.42L11,11.59l3.29-3.3a1,1,0,0,1,1.42,1.42Z"
style="fill:#7dc400"></path>
</svg>
</div>
`;

// add phone number input

const phoneWrapper = document.getElementById("phone-input-container");


const phoneInput = document.createElement("input");
phoneInput.id = "chapa-phone-number";
phoneInput.className = "chapa-phone-input";
phoneInput.type = "tel";
phoneInput.placeholder = "9|7XXXXXXXX";
phoneInput.value = this.options.mobile;
phoneInput.addEventListener("input", (e) => this.validatePhoneNumberOnInput(e));
phoneWrapper.appendChild(phoneInput);
}

handlePayment() {
const phoneNumber =
this.options.mobile ||
document.getElementById("chapa-phone-number").value;
const phoneNumber = document.getElementById("chapa-phone-number").value;


if (
!this.validatePhoneNumber(phoneNumber) ||
!this.validatePaymentMethod()
) {

return;
}

Expand Down Expand Up @@ -147,6 +178,9 @@ class ChapaCheckout {
const paymentMethod = this.paymentMethodIcons[method];
const element = document.createElement("div");
element.className = "chapa-payment-method";
if (method === this.paymentType) {
element.classList.add("chapa-selected");
}
element.innerHTML = `
<img src="${paymentMethod.icon}" alt="${paymentMethod.name}" class="chapa-payment-icon">
${
Expand Down Expand Up @@ -181,26 +215,28 @@ class ChapaCheckout {
const style = document.createElement("style");
style.id = "chapa-styles";
style.textContent = `
.chapa-error { display: none; color: red; margin-bottom: 10px; }
.chapa-error { display: none; color: red; margin-bottom: 10px; margin-top: 10px; }
.chapa-loading { display: none; text-align: center; margin-top: 15px; }
.chapa-spinner { display: inline-block; width: 30px; height: 30px; border: 3px solid rgba(0,0,0,.1); border-radius: 50%; border-top-color: #7DC400; animation: chapa-spin 1s ease-in-out infinite; }
@keyframes chapa-spin { to { transform: rotate(360deg); } }
.chapa-payment-methods-grid { display: flex; justify-content: space-between; gap: 8px; margin: 15px 0; }
.chapa-payment-methods-grid { display: flex; gap: 8px; margin: 15px 0; justify-content: space-between; }
.chapa-payment-method { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 8px; border: 1px solid #e5e7eb; border-radius: 4px; cursor: pointer; width: 60px; height: 60px; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15); }
.chapa-payment-icon { width: 42px; height: 42px; margin-bottom: 4px; }
.chapa-payment-name { font-size: 11px; text-align: center; }
.chapa-selected { background-color: #e6fffa; box-shadow: 0 0 0 2px #10b981; }
.chapa-input-wrapper { margin-bottom: 10px; }
.chapa-selected { background-color: #7dc40024; box-shadow: 0 0 0 1px #7DC400; }
.chapa-input-wrapper { margin-bottom: 10px; ] }
.chapa-input-wrapper label { display: block; margin-bottom: 5px; font-weight: 600; color: #333; }
.chapa-input { width: 100%; padding: 12px; border: 1px solid #d1d5db; border-radius: 8px; font-size: 16px; outline: none; box-sizing: border-box; transition: border-color 0.3s, box-shadow 0.3s; }
.chapa-input:focus { border-color: #10b981; box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.2); }
.chapa-phone-input-wrapper { position: relative; margin-bottom: 20px; display: flex; align-items: center; }
.chapa-input:focus { border-color: #7DC400; box-shadow: 0 0 0 3px #7dc40024; }
.chapa-phone-input-wrapper { position: relative; margin-bottom: 20px; display: flex; align-items: center; border: 1px solid #d1d5db; border-radius: 8px; padding: 8px 12px; }
.chapa-phone-prefix { display: flex; align-items: center; padding: 0 12px; background-color: #ffffff; border-radius: 7px 0 0 7px; height: 100%; font-size: 16px; color: #6b7280; }
.chapa-flag-icon { width: 24px; height: auto; margin-right: 8px; }
.chapa-phone-input { width: 100%; padding: 12px; border: 1px solid #d1d5db; border-radius: 8px; font-size: 16px; outline: none; box-sizing: border-box; transition: border-color 0.3s, box-shadow 0.3s; }
.chapa-phone-input:focus { border-color: #10b981; box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.2); }
.chapa-phone-input { width: 100%; padding: 10px; border: none; border-left: 1px solid #d1d5db; font-size: 18px; outline: none !important; box-shadow: none !important; box-sizing: border-box; transition: border-color 0.3s, box-shadow 0.3s; }
.chapa-phone-input-wrapper:hover { border-color: #7DC400; box-shadow: 0 0 0 3px #7dc40024; }
.chapa-phone-input-wrapper:hover .chapa-phone-input { border-color: #7DC400; box-shadow: 0 0 0 3px #7dc40024; }
.chapa-pay-button { background-color: #7DC400; color: #FFFFFF; border: none; border-radius: 4px; padding: 10px; font-size: 16px; cursor: pointer; width: 100%; transition: background-color 0.3s; }
.chapa-pay-button:hover { background-color: #6baf00; }
#phone-input-container { width: 100%; }
`;
document.head.appendChild(style);
}
Expand All @@ -211,44 +247,39 @@ class ChapaCheckout {
document.head.appendChild(customStyle);
}

this.adjustPhoneInputPadding();
window.addEventListener("resize", () => this.adjustPhoneInputPadding());
}

adjustPhoneInputPadding() {
const prefix = document.querySelector(".chapa-phone-prefix");
const input = document.querySelector(".chapa-phone-input");
if (prefix && input) {
const prefixWidth = prefix.offsetWidth;
input.style.paddingLeft = `${prefixWidth + 12}px`;
}

}


validatePhoneNumber(phoneNumber) {
if (phoneNumber.startsWith("0")) {
phoneNumber = phoneNumber.substring(1);
} else if (phoneNumber.startsWith("251")) {
phoneNumber = phoneNumber.substring(3);
} else if (phoneNumber.startsWith("+251")) {
phoneNumber = phoneNumber.substring(4);
}

const firstDigit = phoneNumber.charAt(0);
if (
phoneNumber.length !== 9 ||
(firstDigit !== "9" && firstDigit !== "7")
) {
this.showError("Please enter a valid Ethiopian phone number.");
const mobileRegex = /^(251\d{9}|0\d{9}|9\d{8}|7\d{8})$/;
if (!mobileRegex.test(phoneNumber)) {
this.showError("Please enter a valid Phone Number.");
return false;
}
if (this.paymentType === "telebirr" && firstDigit !== "9") {
this.showError("Please enter a valid telebirr mobile number.");


if(phoneNumber.charAt(0) === '0'){
phoneNumber = phoneNumber.slice(1);
}
const telebirrRegex = /^(2519\d{8}|9\d{8})$/;

if (this.paymentType === "telebirr" && telebirrRegex.test(phoneNumber) === false) {
this.showError("Please enter a valid Telebirr Phone Number.");
return false;

}
if (this.paymentType === "mpesa" && firstDigit !== "7") {
this.showError("Please enter a valid M-Pesa mobile number.");

const mpesaRegex = /^(2519\d{8}|7\d{8})$/;

if (this.paymentType === "mpesa" && mpesaRegex.test(phoneNumber) === false) {
this.showError("Please enter a valid Mpesa Phone Number.");
return false;

}



return true;
}

Expand Down

0 comments on commit 84dffe1

Please sign in to comment.