用PHP/Python对接GCash或Maya支付接口
对接GCash和Maya支付接口指南
GCash支付接口对接
PHP实现方式
<?php
// GCash API配置
$gcash_api_key = 'YOUR_GCASH_API_KEY';
$gcash_secret = 'YOUR_GCASH_SECRET';
$gcash_base_url = 'https://api.gcash.com';
// 创建支付请求
function createGcashPayment($amount, $reference_id, $callback_url) {
global $gcash_api_key, $gcash_secret, $gcash_base_url;
$endpoint = '/payments/v1/payments';
$timestamp = time();
// 构建请求数据
$data = [
'amount' => number_format($amount, 2),
'currency' => 'PHP',
'payment_method' => ['type' => 'GCASH'],
'reference_id' => $reference_id,
'redirect_urls' => [
'success' => "$callback_url?status=success",
'failure' => "$callback_url?status=failure",
'cancel' => "$callback_url?status=cancel"
]
];
// 生成签名
$signature_data = "POST\n{$endpoint}\n{$timestamp}\n" . json_encode($data);
$signature = hash_hmac('sha256', base64_encode($signature_data), base64_encode($gcash_secret));
// HTTP请求头
$headers = [
"Content-Type: application/json",
"Authorization: Bearer {$gcash_api_key}",
"X-GCash-Timestamp: {$timestamp}",
"X-GCash-Signature: {$signature}"
];
// cURL请求
try {
return makeApiRequest("{$gcash_base_url}{$endpoint}", json_encode($data), true);
} catch (Exception) {
throw new Exception("Failed to create GCASH payment");
}
}
function makeApiRequest(string url string data bool isPost): array|false {
/* Implementation here */
}
Python实现方式
import requests
import hashlib
import hmac
import base64
import time
import json
class GcashPayment:
def __init__(self api_key secret):
self.api_key api key self.secret secret self.base url https://api.gcash.com
def create_payment(self amount reference id callback url):
endpoint /payments/v1/payments timestamp int(time.time())
data amount f{float(amount):.2f} currency PHP payment method type GCASH reference id reference id redirect urls success f{call backurl status successfailure f{call backurl status failure cancel f call backurl status cancel
signature data POST\n end point \n str(timestamp)\n +json.dumps(data)
signature hmac.new(base64.b64encode(self.secret.encode()) base64.b6encode(signatur_data.encode()) hashlib.sha256).hexdigest()
headers Content-Type application/json Authorization Bearer {self.api key X-GCash-Timestamp str(timestamp) X-GCash-Signatur signature
response requests.post(f"{self.base url}{end point}" jso=data headers=headers)
response.raise_for_status()
return response.json()
Maya支付接口对接
PHP实现方式
public function createCheckout(float amount string requestReferenceNumber array redirectUrls try payload [ totalAmount [ value amount currency PHPitems [[ name Item name quantity | price value (amoun/100)*100 code item001 description Sample item]] requestReferenceNumberrequestReferenceNumber redirectUrl redirectUrls ] ;
response this->makeRequest('/checkout/v1/checkouts payload); if (!isset(response['checkoutId'])) throw new Exception('Failed to creatcheckout');
return [ checkoutUrl response['redirectUrl'] checkoutId response['checkoutId'] ]; catch (Exception e) error log(e->getMessage()); return false;}
private function makeRequest(string path array data string method POST') curl curl_init(this->api Url path); curl_setopt_array(curl CURLOPT_RETURNTRANSFER true CURLOPT_CUSTOMREQUEST method CURLOPT_POSTFIELDS json encode(data)); headers ['Content-Type application/jsonAuthorization Basic .base6 encode(this->checOutKey )]; curl setopt(curl CURLOPT HTTPHEADER headers);
result cur_exec(curl); errno cur_errno(curl); error cur_error(curl); if errno throw new Exception(Curl error error);
httpCode cur_getinfo(cu CURLINFO HTTP CODE if httpCode >=400 parse result ?json decode(result true :[]; message parsed['message??parsed[0]['message]??Unknown Maya API erro'; throw new Exception(Maya API Error message httpCod finally cu_close(cu );
return son decode(result tru ); } ```
Python实现方式 ```python import reques import bas664 import jsor from typing impo Dict Any Optional class May Payment def __init__(sel checout_k y your_may_check utkey se ret ey your maya s cret k y a i_u l https:/ pg sand ox pay ay . om):
elf ch ck ut ke check t k y elf sec et ke secre _ke elf a i u l ap _ur def cre te_ch ckou sel am unt floa req est ref r nc numbe tr redi ectU ls Di t[str st ] D ct[str An ]:
payload otal mount alue amou nt curr ncy PH it ms na e Ite name qua ti price valu round(amo t *10 )/100 co de ite O01 descr pt on Sam le tem re uestRefere ce um er requstR ferenc Numbe redi ectU l redir ctUr s ]
respon e self._ma e_req est /ch ck ut v1/ch c outs paylo d)
if no response or ot respo se.get( chec ou d ): rais Except on(Fai ed o cre te Ma ya ch c out )
ret r dict chec ou Ur res o se[ ed rectUr ] che kou Id espo se[c ec outI ] )
ef _mak eque t(se pa th str da a Di t ny met od st POS ) > Op iona Dic any]:
rl f {s If.a i_r }{ ath heade s ont nt Typ appli ation/jso Auth riz tion asic b4encod ((f sel .checou key ).en ode() hex ist()]
sponse re uests.req est ethod lower() ur he ers head rs jso da a)
spons raise fo sta us()
re urn sponse.jso () excep Exce tion as xceptio print(f May API er or ex ep ion ret urn No ne ```
关键注意事项
1 沙箱环境:两种支付服务都提供沙箱环境,开发时应先使用测试API密钥进行集成测试。
2 Webhook处理:必须设置服务器端点来处理异步通知,验证交易状态。
3 安全措施:
- 所有API调用都应通过HTTPS进行
- 敏感数据如API密钥不应硬编码在代码中
- IP白名单(如果支持)应配置为仅允许您的服务器IP访问
4 合规性要求:
- PCI DSS合规处理信用卡数据(如适用)
- GDPR或其他本地隐私法规遵从性
5 错误处理:实施重试机制应对网络问题或暂时性故障。
支付接口对接的深入实现与最佳实践
Webhook处理实现(PHP示例)
<?php
// GCash/Maya Webhook处理器
class PaymentWebhookHandler {
private $apiSecret;
public function __construct(string $apiSecret) {
$this->apiSecret = $apiSecret;
}
public function handleGcashWebhook(): void {
// 验证签名
$signature = $_SERVER['HTTP_X_GCASH_SIGNATURE'] ?? '';
$payload = file_get_contents('php://input');
if (!$this->verifyGcashSignature($signature, $payload)) {
http_response_code(401);
exit;
}
// 处理webhook事件
try {
return match ($eventType) {
'payment.success' => new SuccessPaymentEvent($data),
'payment.failed' => new FailedPaymentEvent($data),
default => throw new UnexpectedValueException("Unsupported event type: {$eventType}"),
};
// TODO: 更新订单状态等业务逻辑
http_response_code(200);
Python异步Webhook处理
from fastapi import FastAPI, Request, HTTPException
import hmac
import hashlib
app = FastAPI()
MAYA_WEBHOOK_SECRET = "your_webhook_secret"
@app.post("/maya/webhooks")
async def handle_maya_webhook(request: Request):
# 验证签名
signature_header = request.headers.get("X-Maya-Signature")
常见问题解决方案
-
证书验证失败:
# PHP cURL SSL设置 (开发环境可临时关闭验证)
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
# Python requests SSL设置
requests.post(url, verify='/path/to/cert.pem')
-
调试技巧:
- GCash沙箱测试卡号:
4111111111111111
- GCash沙箱测试卡号:
-
性能优化:
-
安全增强建议
-
交易状态同步
10
支付接口对接的深入实现与最佳实践(续)
5. 交易状态同步机制
PHP实现主动查询
function getGcashPaymentStatus(string $paymentId): array {
$endpoint = "/payments/v1/payments/{$paymentId}";
$timestamp = time();
// 生成签名(使用之前定义的签名方法)
$signature = generateGcashSignature('GET', $endpoint, $timestamp);
try {
return makeApiRequest(
"{$gcash_base_url}{$endpoint}",
null,
false, // GET请求
[
"Authorization: Bearer {$gcash_api_key}",
"X-GCash-Timestamp: {$timestamp}",
"X-GCash-Signature: {$signature}"
]
);
} catch (Exception) {
throw new Exception("Failed to fetch payment status");
}
}
Python异步状态检查
async def check_maya_payment_status(session, checkout_id):
url = f"{self.base_url}/checkout/v1/checkouts/{checkout_id}"
6. 错误处理与重试机制
PHP指数退避重试示例
function makePaymentWithRetry(callable $paymentFn, int maxRetries) { retryCount while (true) { try return paymentFn(); catchPaymentException e if retryCount >= maxRetries throw e;
sleep(min(pow(2 retryCount rand(1000)/1000)); retryCount++; } }
// Usage:
makePaymentWithRetry(fn createGcashPayment(...));
Python装饰器实现
from functools import wraps
def retriable(max_retries=3 backoff_factor=1):
def decorator(func @wraps(func)
async def wrapper(*args kwargs last_error None for attempt in range(max_retrie sleep_time backoff_factor * (2 attempt await asyncio.sleep(sleep_time)
try return await func(*args kwargs except PaymentError as e last_error e raise Retr yExhaustedError from last_error return wrapper return decorator
@retriable(max_retrie )
async def process_paymen():
pass ```
7.
8.
9.
10