如何在马来西亚地区应用中集成IPay88支付网关SDK?
Hey there! I’ve implemented iPay88’s Java SDK for Malaysian e-commerce apps before, so let’s walk through a practical step-by-step guide tailored to your setup. You’ve already got the key pieces (merchant code, secret key, and the JAR file) so we can jump straight into integration.
First, let’s get the SDK set up in your project:
- If you’re using a non-Maven/Gradle project: Drop the downloaded JAR file into your project’s
libfolder, then mark it as a library in your IDE (e.g., in IntelliJ, right-click the JAR → Add as Library). - If you’re using Maven: Since iPay88’s JAR isn’t in Maven Central, you’ll need to install it locally using this command (replace paths with your actual file locations):
mvn install:install-file -Dfile=/path/to/ipay88-sdk.jar -DgroupId=com.ipay88 -DartifactId=ipay88-sdk -Dversion=1.0 -Dpackaging=jar
Then add this dependency to your pom.xml:
<dependency> <groupId>com.ipay88</groupId> <artifactId>ipay88-sdk</artifactId> <version>1.0</version> </dependency>
Create a configuration class to store your merchant credentials and endpoints (keep these secure—never hardcode them in production; use environment variables or a secrets manager):
public class IPay88Config { // Replace with your actual merchant code public static final String MERCHANT_CODE = "YOUR_MERCHANT_CODE"; // Replace with your actual merchant key public static final String MERCHANT_KEY = "YOUR_MERCHANT_KEY"; // Production payment URL; use the sandbox URL for testing public static final String PAYMENT_ENDPOINT = "https://www.mobile88.com/epayment/entry.asp"; // Your app's callback URL (must be publicly accessible for iPay88 to reach) public static final String CALLBACK_ENDPOINT = "https://your-app-domain.com/api/ipay88/callback"; }
To redirect users to iPay88’s payment page, you’ll need to generate a signed payment form. The signature is critical—iPay88 uses MD5 hashing with a strict parameter order to verify requests.
Here’s a service class to handle this:
import java.security.MessageDigest; import java.util.HashMap; import java.util.Map; public class IPay88PaymentService { public String generatePaymentForm(String orderId, double amount, String customerName, String customerEmail, String customerPhone) { // Build payment parameters (follow iPay88's required fields) Map<String, String> paymentParams = new HashMap<>(); paymentParams.put("MerchantCode", IPay88Config.MERCHANT_CODE); paymentParams.put("PaymentId", "1"); // 1 = Credit Card; check iPay88 docs for other payment methods paymentParams.put("RefNo", orderId); // Your unique order ID paymentParams.put("Amount", String.format("%.2f", amount)); // Must be 2 decimal places (e.g., "100.00") paymentParams.put("Currency", "MYR"); // Only MYR is supported for Malaysia paymentParams.put("ProdDesc", "Your Product/Service Description"); paymentParams.put("UserName", customerName); paymentParams.put("UserEmail", customerEmail); paymentParams.put("UserContact", customerPhone); paymentParams.put("Lang", "EN"); // Use "ZH" for Chinese paymentParams.put("ResponseURL", IPay88Config.CALLBACK_ENDPOINT); // Generate and add the signature paymentParams.put("Signature", generateRequestSignature(paymentParams)); // Build an auto-submitting HTML form to redirect users to iPay88 StringBuilder formBuilder = new StringBuilder(); formBuilder.append("<form id='ipay88-payment-form' action='").append(IPay88Config.PAYMENT_ENDPOINT).append("' method='POST'>"); for (Map.Entry<String, String> entry : paymentParams.entrySet()) { formBuilder.append(String.format("<input type='hidden' name='%s' value='%s'>", entry.getKey(), entry.getValue())); } formBuilder.append("<button type='submit'>Proceed to iPay88 Payment</button>"); formBuilder.append("</form>"); formBuilder.append("<script>document.getElementById('ipay88-payment-form').submit();</script>"); return formBuilder.toString(); } private String generateRequestSignature(Map<String, String> params) { // Signature order: MerchantCode + RefNo + Amount + Currency + MerchantKey String signatureRaw = params.get("MerchantCode") + params.get("RefNo") + params.get("Amount") + params.get("Currency") + IPay88Config.MERCHANT_KEY; try { MessageDigest md = MessageDigest.getInstance("MD5"); byte[] hashBytes = md.digest(signatureRaw.getBytes("UTF-8")); StringBuilder hexSignature = new StringBuilder(); for (byte b : hashBytes) { String hex = Integer.toHexString(0xff & b); if (hex.length() == 1) hexSignature.append('0'); hexSignature.append(hex); } return hexSignature.toString().toUpperCase(); } catch (Exception e) { throw new RuntimeException("Failed to generate payment signature", e); } } }
Important note: The signature parameter order is non-negotiable. If you mix up the order, iPay88 will reject your request.
After the user completes payment, iPay88 will send a POST request to your callback URL. You need to:
- Validate the callback signature to ensure it’s legitimate.
- Update your order status based on the payment result.
- Return
RECEIVEOKto iPay88 (otherwise, they’ll keep retrying the callback).
Here’s a handler for the callback:
import javax.servlet.http.HttpServletRequest; import java.security.MessageDigest; import java.util.HashMap; import java.util.Map; public class IPay88CallbackHandler { public void processCallback(HttpServletRequest request) { // Extract callback parameters String merchantCode = request.getParameter("MerchantCode"); String refNo = request.getParameter("RefNo"); String amount = request.getParameter("Amount"); String currency = request.getParameter("Currency"); String status = request.getParameter("Status"); // 1 = Success; 0 = Failed String callbackSignature = request.getParameter("Signature"); // Validate the signature first if (!isValidCallbackSignature(merchantCode, refNo, amount, currency, status, callbackSignature)) { System.out.println("Invalid callback signature for order: " + refNo); // Return error response (iPay88 will retry) return; } // Process the payment result if ("1".equals(status)) { // Payment successful: Update your order to "Paid" in the database, send confirmation email, etc. System.out.println("Payment successful for order: " + refNo + " | Amount: " + amount); } else { // Payment failed: Mark order as "Failed", notify the user, etc. System.out.println("Payment failed for order: " + refNo + " | Status code: " + status); } // MUST return "RECEIVEOK" to iPay88 to stop retries System.out.println("RECEIVEOK"); } private boolean isValidCallbackSignature(String merchantCode, String refNo, String amount, String currency, String status, String incomingSignature) { // Callback signature order: MerchantCode + RefNo + Amount + Currency + Status + MerchantKey String validationRaw = merchantCode + refNo + amount + currency + status + IPay88Config.MERCHANT_KEY; try { MessageDigest md = MessageDigest.getInstance("MD5"); byte[] hashBytes = md.digest(validationRaw.getBytes("UTF-8")); StringBuilder hexSignature = new StringBuilder(); for (byte b : hashBytes) { String hex = Integer.toHexString(0xff & b); if (hex.length() == 1) hexSignature.append('0'); hexSignature.append(hex); } String generatedSignature = hexSignature.toString().toUpperCase(); return generatedSignature.equals(incomingSignature); } catch (Exception e) { return false; } } }
- Use iPay88’s sandbox environment first (replace the payment endpoint with their sandbox URL).
- Test with their dummy payment details (e.g., Visa card: 4111111111111111, expiry: any future date, CVV: 123).
- Ensure your callback URL is publicly accessible (use tools like ngrok if you’re testing locally).
内容的提问来源于stack exchange,提问作者Paras Andani

