Braintree PHP SDK新手求助:订阅成功时获取属性并保存客户信息至数据库
处理Braintree订阅成功Webhook,保存客户详情到数据库
嘿,作为编程新手能搞定Webhook URL配置已经超棒了!咱们一步步来解决你的问题:
一、先明确要监听的Webhook事件
Braintree里和订阅成功相关的核心事件有两个,你可以根据自己的订阅模式选择:
SubscriptionWentActive:当订阅从试用状态转为活跃,或者首次创建就直接活跃时触发(这是最常用的“订阅成功”场景)SubscriptionCreated:订阅首次创建时触发(如果你的订阅是立即生效,这个也能用,但如果有试用环节,还是前者更准确)
二、完整的Webhook处理流程(含安全验证)
首先必须做Webhook签名验证,这是安全刚需,能防止恶意伪造请求。下面是完整的PHP代码示例,你可以把它整合到你现有的public static function里:
use Braintree\WebhookNotification; public static function handleBraintreeWebhook() { // 1. 获取Braintree发送的请求签名和原始数据 $btSignature = $_SERVER['HTTP_BRAINTREE_SIGNATURE'] ?? ''; $btPayload = file_get_contents('php://input'); try { // 2. 验证签名并解析Webhook事件 $webhookNotification = WebhookNotification::parse($btSignature, $btPayload); // 3. 只处理订阅成功的事件 $targetKinds = [ Braintree\WebhookNotification::SUBSCRIPTION_WENT_ACTIVE, Braintree\WebhookNotification::SUBSCRIPTION_CREATED ]; if (in_array($webhookNotification->kind, $targetKinds)) { // 获取订阅对象,拿到核心订阅参数 $subscription = $webhookNotification->subscription; // 通过订阅关联的customerId,获取完整客户详情 $customer = Braintree\Customer::find($subscription->customerId); // 4. 把客户详情保存到数据库(这里用PDO示例,你可以换成自己的ORM框架) $pdo = new PDO('mysql:host=localhost;dbname=你的数据库名', '用户名', '密码'); $stmt = $pdo->prepare("INSERT INTO customers (braintree_customer_id, email, first_name, last_name, created_at) VALUES (:customer_id, :email, :first_name, :last_name, NOW())"); $stmt->execute([ ':customer_id' => $customer->id, ':email' => $customer->email, ':first_name' => $customer->firstName ?? '', ':last_name' => $customer->lastName ?? '' ]); // 可选:也可以把订阅信息同步到数据库 $stmtSub = $pdo->prepare("INSERT INTO subscriptions (braintree_sub_id, customer_id, plan_id, status, next_billing_date) VALUES (:sub_id, :customer_id, :plan_id, :status, :next_billing)"); $stmtSub->execute([ ':sub_id' => $subscription->id, ':customer_id' => $customer->id, ':plan_id' => $subscription->planId, ':status' => $subscription->status, ':next_billing' => $subscription->nextBillingDate->format('Y-m-d') ]); // 返回200状态码给Braintree,说明事件已处理成功 http_response_code(200); echo "Webhook processed successfully"; } else { // 其他类型的Webhook事件可以按需处理,或者直接返回200 http_response_code(200); echo "Unhandled webhook kind: " . $webhookNotification->kind; } } catch (Braintree\Exception\InvalidSignature $e) { // 签名验证失败,返回403禁止访问 http_response_code(403); echo "Invalid webhook signature"; error_log("Braintree Webhook验证失败: " . $e->getMessage()); } catch (Exception $e) { // 处理其他异常,比如数据库连接错误等 http_response_code(500); echo "Error processing webhook: " . $e->getMessage(); error_log("Braintree Webhook处理错误: " . $e->getMessage()); } }
三、常用的订阅/客户属性清单
拿到$subscription和$customer对象后,你可以直接调用这些常用属性:
订阅属性($subscription)
id:Braintree生成的唯一订阅IDplanId:订阅对应的套餐IDstatus:订阅状态(active/canceled/past_due等)customerId:关联的客户IDnextBillingDate:下次账单日期(DateTime对象,可通过format()转成字符串)price:订阅的单价
客户属性($customer)
id:Braintree生成的唯一客户IDemail:客户注册邮箱firstName/lastName:客户姓名phone:客户联系电话createdAt:客户账号创建时间(DateTime对象)
四、验证你现有代码的几个关键点
你可以对照下面几点检查自己的代码是否可用:
- ✅ 是否做了Webhook签名验证?这是必须的,不然会有安全漏洞
- ✅ 是否正确判断了订阅成功的事件类型?
- ✅ 是否通过
$webhookNotification->subscription获取到了完整的订阅对象? - ✅ 是否通过客户ID拉取了完整的客户信息(而不是只取订阅里的零散数据)?
- ✅ 数据库操作是否用了参数绑定(防止SQL注入)?
内容的提问来源于stack exchange,提问作者marc torne
相关产品推荐
相关产品推荐

