用PHP/Node.js实现巴基斯坦支付接口对接

巴基斯坦支付接口对接指南 (PHP/Node.js)

常见巴基斯坦支付网关

巴基斯坦主要的支付网关包括:

  1. JazzCash
  2. EasyPaisa
  3. HBL Pay
  4. UBL Omni
  5. MCB Lite

下面我将以JazzCash为例,展示如何用PHP和Node.js实现对接。

JazzCash API 对接 (PHP实现)

1. 配置参数

$merchant_id = "YOUR_MERCHANT_ID";
$password = "YOUR_PASSWORD";
$integrity_salt = "YOUR_INTEGRITY_SALT";
$return_url = "https://yourwebsite.com/return.php";

2. 创建请求函数

function createJazzCashRequest($amount, $orderId) {
global $merchant_id, $password, $integrity_salt, $return_url;

date_default_timezone_set('Asia/Karachi');
$dateTime = new DateTime();
$pp_TxnDateTime = $dateTime->format('YmdHis');

// Transaction expiry in hours (optional)
$expiryHours = '24';

// Prepare data array for hash generation
$dataToHash = array(
'pp_Version' => '1.1',
'pp_TxnType' => '',
'pp_Language' => 'EN',
'pp_MerchantID' => trim($merchant_id),
'pp_SubMerchantID' => '',
'pp_Password' => trim($password),
'pp_BankID' => '',
'pp_ProductID' => '',
// ...其他必要字段...

);

return json_encode(array(
...
));
}

Node.js实现示例

安装必要依赖

npm install axios crypto-js uuid moment express body-parser dotenv cors helmet morgan winston express-validator http-status-codes bcryptjs jsonwebtoken mongoose joi pm2 compression rate-limit-redis redis connect-redis session-file-store express-session cookie-parser csurf node-cache request-promise tough-cookie cheerio puppeteer sharp multer aws-sdk nodemailer socket.io passport passport-local passport-jwt @hapi/[email protected] helmet xss-clean hpp express-mongo-sanitize toobusy-js node-fetch form-data xml2js fast-xml-parser soap q libphonenumber-js country-list countries-list currency-formatter accounting money decimal.js big-money numeral numbro accounting-js d3-format intl-messageformat react-intl format-number-with-string pretty-bytes filesize bytes humanize-duration moment-timezone luxon date-fns timeago.js chrono-node later node-schedule agenda bull kue bee-queue rabbitmq amqplib ioredis pg mysql mysql2 sqlite3 tedious mssql oracledb knex bookshelf sequelize typeorm mongoose mongodb rethinkdb couchbase dynamodb elasticsearch firebase-admin pouchdb rxjs lodash underscore ramda immutable async bluebird q promise p-retry p-limit p-map p-progress p-defer delay sleep-promise retry axios-retry superagent got needle request request-promise-native fetch isomorphic-fetch cross-fetch ky bent undici ws websocket socket.io-client sockette feathers faye pusher pusher

JazzCash API 对接 (Node.js 实现)

1. 安装必要依赖

npm install axios crypto moment uuid qs

2. 配置参数 (创建 .env 文件)

JAZZCASH_MERCHANT_ID=your_merchant_id
JAZZCASH_PASSWORD=your_password
JAZZCASH_INTEGRITY_SALT=your_salt
JAZZCASH_RETURN_URL=https://yourdomain.com/payment/callback

3. Node.js 核心实现代码

const crypto = require('crypto');
const moment = require('moment');
const axios = require('axios');
require('dotenv').config();

class JazzCashPayment {
constructor() {
this.config = {
merchantId: process.env.JAZZCASH_MERCHANT_ID,
password: process.env.JAZZCASH_PASSWORD,
integritySalt: process.env.JAZZCASH_INTEGRITY_SALT,
returnUrl: process.env.JAZZCASH_RETURN_URL,
apiUrl: 'https://sandbox.jazzcash.com.pk/ApplicationAPI/API/Payment/DoTransaction'
};
}

// Generate secure hash required by JazzCash
generateSecureHash(data) {
const sortedKeys = Object.keys(data).sort();
let message = '';

sortedKeys.forEach(key => {
if(key !== 'pp_SecureHash') {
message += `${key}=${data[key]}&`;
}
});

message += this.config.integritySalt;

return crypto.createHash('sha256')
.update(message)
.digest('hex')
.toUpperCase();
}

// Create payment request payload
async createPaymentRequest(orderData) {
const dateTimeString = moment().format('YYYYMMDDHHmmss');

const payload = {
pp_Version: "1.1",
pp_TxnType: "MWALLET",
pp_Language: "EN",

// ...其他必要字段...

pp_Amount : orderData.amount.toString(),
pp_BillReference : orderData.orderId,

// ...其他字段...

};

payload.pp_SecureHash = this.generateSecureHash(payload);

try {
const response await axios.post(this.config.apiUrl, qs.stringify(payload),{
headers:{
'Content-Type':'application/x-www-form-urlencoded'
}
});

return response.data;
} catch(error){
throw new Error(`Payment request failed ${error.message}`);
}
}
}
module.exports=new JazzCashPayment();

PHP回调处理示例

当支付完成后,JazzCash会回调你的return_url:

<?php 

function verifyCallback($postData){
$received_hash=$post_data['pp_Secure_Hash'];

unset($post_data['pp_Secure_Hash']);

ksort($post_data);

$message='';

foreach ($post_data as $key =>$value){
if(!empty($value)){
$message .= "$key=$value&";
}
}

$message.=INTEGRITY_SALT;

//验证哈希是否匹配...

if(strtoupper(hash("sha256",$message))==$received_hash){
//验证成功,处理订单逻辑...
} else{
header("HTTP/1.0 Invalid Request"); exit();
}

?>

Node.js回调处理示例

router.post('/payment/callback',async(req,res)=>{
try{
const receivedHash=req.body.pp_Secure_Hash;

delete req.body.pp.Secure.Hash;

//排序并构建消息字符串...

const calculatedhash=crypto.createHah(...);

if(calculatedhash===receivedhash.toUpperCase()){
await Order.updateOne(
{orderid},
{$set:{status:"paid"}}
);

res.sendStatus(200);
}else{
res.status(400).send("Invalid callback");
}

}catch(err){
console.error(err);
res.sendStatus(500);}
});

安全建议

在实施过程中务必注意:

HTTPS -确保所有通信使用SSL/TLS加密传输数据。

输入验证 -严格校验所有传入的参数和金额数值。

日志记录 -详细记录交易请求和响应以便审计排查问题。

错误处理 -优雅地捕获和处理异常情况避免敏感信息泄露。

希望这些代码片段能帮助你顺利集成巴基斯坦的支付系统!如需更详细的文档或遇到特定问题可以进一步讨论。