Laravel 8使用srmklive Paypal v1付款成功后如何将账单存入customer_details表
实现方案
一、处理位置说明
客户账单存储必须在服务端PayPalController中完成,无需调用JavaScript/Ajax处理。前端提交的信息存在被篡改的风险,只有PayPal回调到服务端的经过校验的支付数据才是可信的,避免出现伪造支付成功写入账单的漏洞。
二、具体实现步骤
步骤1:创建对应模型与数据库迁移
首先执行Artisan命令生成模型和迁移文件:
php artisan make:model CustomerDetail -m
打开生成的迁移文件(database/migrations/xxxx_xx_xx_xxxxxx_create_customer_details_table.php),编辑字段结构,示例如下:
public function up() { Schema::create('customer_details', function (Blueprint $table) { $table->id(); $table->unsignedBigInteger('invoice_id'); // 关联订单ID $table->string('payer_email'); // 付款人PayPal邮箱 $table->string('payer_id'); // PayPal付款人唯一ID $table->string('first_name'); // 名 $table->string('last_name'); // 姓 $table->string('ship_to_street')->nullable(); // 收货街道 $table->string('ship_to_city')->nullable(); // 收货城市 $table->string('ship_to_state')->nullable(); // 收货省份/州 $table->string('ship_to_zip')->nullable(); // 收货邮编 $table->string('ship_to_country_code')->nullable(); // 收货国家代码 $table->string('transaction_id')->nullable(); // PayPal交易号 $table->timestamps(); // 外键关联,可选配置 $table->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade'); }); }
执行迁移生成表:
php artisan migrate
步骤2:修改PayPalController逻辑
首先在控制器顶部引入CustomerDetail模型:
use App\CustomerDetail;
找到getExpressCheckoutSuccess方法,在创建账单$invoice = $this->createInvoice($cart, $status);之后,添加存储客户信息的逻辑:
$invoice = $this->createInvoice($cart, $status); // 新增:付款成功后存储客户详情 if ($invoice->paid) { $customerDetail = new CustomerDetail(); $customerDetail->invoice_id = $invoice->id; // 从PayPal校验成功的响应中取客户信息 $customerDetail->payer_email = $response['EMAIL']; $customerDetail->payer_id = $response['PAYERID']; $customerDetail->first_name = $response['FIRSTNAME']; $customerDetail->last_name = $response['LASTNAME']; $customerDetail->ship_to_street = $response['SHIPTOSTREET'] ?? ''; $customerDetail->ship_to_city = $response['SHIPTOCITY'] ?? ''; $customerDetail->ship_to_state = $response['SHIPTOSTATE'] ?? ''; $customerDetail->ship_to_zip = $response['SHIPTOZIP'] ?? ''; $customerDetail->ship_to_country_code = $response['SHIPTOCOUNTRYCODE'] ?? ''; // 非订阅模式下取交易号 if (!$recurring) { $customerDetail->transaction_id = $payment_status['PAYMENTINFO_0_TRANSACTIONID'] ?? ''; } $customerDetail->save(); session()->put(['code' => 'success', 'message' => "Order $invoice->id has been paid successfully!"]); } else { session()->put(['code' => 'danger', 'message' => "Error processing PayPal payment for Order $invoice->id!"]); }
可选优化:IPN回调补充存储
为了避免用户支付完成后直接关闭页面,没跳转到getExpressCheckoutSuccess回调导致数据丢失,建议在notify IPN回调方法中也增加存储逻辑,PayPal会主动推送支付结果到该接口,数据可靠性更高。
内容的提问来源于stack exchange,提问作者Swimo Omix
相关产品推荐
相关产品推荐

