悠悠楠杉
易支付接入实战指南:从零到上线,手把手教你搞定支付接口
接入第三方支付平台是互联网产品的刚需,但文档晦涩、调试复杂常让开发者头疼。最近帮某奶茶连锁店接入易支付时,我踩遍了所有能踩的坑,今天就把实战经验浓缩成这份保姆级教程。
一、接入前的关键准备
1. 商户注册:登录易支付官网完成企业认证,特别注意「商户类型」选择(线上/线下),这直接影响后续接口权限。
2. 密钥管理:在控制台「安全中心」生成RSA密钥对时,务必保存好以下三样:
- merchant_private.key(商户私钥,绝不可泄露)
- yipay_public.key(平台公钥)
- merchant_id(商户编号)
建议用环境变量存储密钥路径,避免硬编码:
bash
# .env 示例
YIPAY_MERCHANT_ID=123456
YIPAY_PRIVATE_KEY_PATH=/config/merchant_private.key
YIPAY_PUBLIC_KEY_PATH=/config/yipay_public.key
二、支付请求的构建艺术
核心在于签名生成,这是支付安全的生命线。以创建订单为例:
python
import hashlib
import rsa
def createsign(params, privatekeypath):
# 1. 参数按ASCII码升序排序
sortedparams = sorted(params.items())
# 2. 拼接键值对
rawstr = '&'.join([f"{k}={v}" for k,v in sortedparams])
# 3. MD5生成待签名字符串
signstr = hashlib.md5(rawstr.encode()).hexdigest()
# 4. 用商户私钥加密
with open(privatekeypath, 'rb') as f:
privatekey = rsa.PrivateKey.loadpkcs1(f.read())
return rsa.sign(signstr.encode(), privatekey, 'MD5').hex()
请求参数示例:
json
{
"merchant_id": "123456",
"out_trade_no": "ORDER_202307151234",
"total_amount": 15.8,
"subject": "珍珠奶茶x2",
"notify_url": "https://yourdomain.com/callback",
"sign_type": "RSA",
"sign": "5a8f7e3d......" // 上述函数生成
}
三、处理支付跳转的暗坑
1. 页面跳转陷阱:前端收到支付URL后,务必用window.location.replace()而非window.open(),避免苹果浏览器拦截弹窗
2. 支付状态轮询:建议后端实现订单状态查询接口,前端每5秒请求一次:
javascript
const checkPayment = setInterval(async () => {
const res = await fetch(`/api/order/status?order_no=${orderNo}`);
if (res.status === 'paid') {
clearInterval(checkPayment);
showSuccessToast();
}
}, 5000);
四、异步通知的生死防线
这是最易出问题的环节!三点血泪经验:
1. 验证签名第一:拿到通知后先验签,绝对不要先处理业务逻辑
2. 幂等性设计:用out_trade_no+status做Redis锁,防止重复处理
3. 必须返回success:响应失败会导致易支付重试15次,可能引发业务异常
java
// Java验签示例
public boolean verifySign(Map<String, String> params, String publicKeyPath) throws Exception {
String receivedSign = params.get("sign");
params.remove("sign");
String sortedStr = params.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.map(e -> e.getKey() + "=" + e.getValue())
.collect(Collectors.joining("&"));
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initVerify(getPublicKey(publicKeyPath));
signature.update(sortedStr.getBytes());
return signature.verify(Base64.decodeBase64(receivedSign));
}
五、调试地狱逃生指南
遇到问题先查这三类日志:
1. 请求原始报文:用Charles抓包看实际发送内容
2. 平台错误码:易支付error_code特别精准,比如:
- INVALID_SIGN:99%是密钥路径错误或排序算法问题
- EXCEED_LIMIT:通常因测试账户频繁请求触发风控
3. 服务器时间差:调用接口出现TIMESTAMP_EXPIRED?用NTP同步服务器时间
六、上线前的终极checklist
- [ ] 测试环境用沙箱账号(避免产生真实交易)
- [ ] 模拟所有异常场景:断网、支付中途关闭、重复通知
- [ ] 金额边界测试:0.01元(最小单位)、99999.99元(最大值)
- [ ] 准备两套回调URL:一套生产环境,一套本地调试用ngrok穿透
某次上线事故复盘:由于测试环境验签通过,生产环境私钥文件权限设置为600导致Java读取失败,引发大规模支付失败。永远记得检查文件权限!
接入支付不是简单的技术拼装,而是对系统健壮性的深度考验。当看到第一位顾客用手机扫完二维码,奶茶店收银台响起“支付成功”的提示音时,你会觉得这些折腾都值了——毕竟,现金流畅通才是业务的命脉。
