最近一个国外的电商项目,需要对接支付功能,国内的支付一般使用微信支付、支付宝、银联等等,但国际上一般使用Paypal、Skrill、BrainTree、Stripe等,经过内部综合考量所以最后选择使用 Stripe支付。
Stripe的对接相对还是比较简单的,只是相关的文档是英文的,且国内和国外的思想不一样,看文档不是很方便。
做为技术人员这里我将对接中所遇到的问题和解决方法汇总,希望能对开发人员有所帮助。
一:Stripe支付介绍
Stripe支付国际支付还是非常有名气的,具体的介绍下面的一些说明:
- 中文官网:https://stripe.com/zh-cn-us
- Stripe国际支付简介:点击打开
- Stripe支付对接还是非常方便的。
- Stripe支付功能也还是很强大的包括支付、账单、订阅等等。
二:Stripe技术对接
- 对接前的准备工作
- 支付对接方式说明:共有2中方式。
- 方式一:使用Stripe的支付页面进行支付(官方名称:CheckOut)。
- 这种分2种情况:
- 跳转到Stripe的支付页面进行支付,这种类似于支付宝的对接,需要跳转到支付宝的支付页面。Stripe的支付页面效果图如下。
- 自己的页面构建一个Stripe的支付,这种类似于微信公众号的支付。
- 这种分2种情况:
- 方式二:自己做支付页面,通过接口的方式进行支付。
- 官网给出了很多HTML示例效果,可下载后自己修改下。点击查看示例效果
- 采用这种方式,输入信用卡等信息是Stripe通过js控制的,我们是拿不到用户输入的相关信息的,为了安全。
- 不管是使用方式一和方式二,我们都无法获取用户输入的信用卡等信息。
- 推荐使用方式一对接,有以下几点:
- 用户在Stripe输入银行卡信息,用户感觉要更加安全。
- 减少不必要的开发工作,因为自己做的收银页面没法和Stripe的比较。
- 方式一:使用Stripe的支付页面进行支付(官方名称:CheckOut)。
- 下面所有的流程主要是使用跳转到Stripe支付页面支付。
- 简单的流程说明
- 用户点击页面上的“支付”按钮。
- 通过js调用后台的接口,接口中要调用Stripe的接口创建支付的会话(Session),调用Stripe接口之前需要设置一些数据,包括支付金额、支付方式等等,这个后面说明。调用接口成功则Stripe会返回一个SessionId,将该值返会给前端。
- 前端拿到SessionId以后,带上改参数跳转到Stripe的支付页面。
- 用户如果取消支付或支付成功,则跳转到创建Session配置的取消地址和支付成功跳转地址。
- 支付成功或其他的一些事件,Stripe会异步通知我们支付结果。
- 上面这几步骤是大致的流程,还请有多的细节问题。
- 下面我们根据上面简单的流程进行一步步详细的说明。
- 下面的演示代码是:.NET Core
三:发起支付
- 官网有个快速开始支付的说明文档,点击查看
- 做一个HTML页面,页面上需要引用Stripe的js文件和点击跳转到支付按钮。当然支付的页面上还有很多其他的一些东西,比如收货地址、商品信息等等。
-
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script src="~/js/jquery-1.12.4.min.js"></script> <script src="http://js.stripe.com/v3/"></script> </head> <body> <button id="checkout-button">去付款</button> <script type="text/javascript"> //创建一个stripe,里面的参数则是stripe申请的公钥,在后台能查看到,pk_开通的,加test表示是测试的 var stripe = Stripe('pk_test_xxxxxx'); var checkoutButton = document.getElementById('checkout-button'); //支付按钮点击事件 checkoutButton.addEventListener('click', function () { //调用后端的接口 fetch('/create-checkout-session', { method: 'POST', }) .then(function (response) { return response.json(); }) .then(function (session) { //调用后端接口成功,得到sessionId,页面会在函数里面进行跳转 return stripe.redirectToCheckout({ sessionId: session.id }); }) .then(function (result) { if (result.error) { alert(result.error.message); } }) .catch(function (error) { console.error('Error:', error); }); }); </script> </body> </html>
- 上面的页面中需要一个后台调用Stripe来产生SessionId。
- 后端代码,VS上先在NuGet上引用第三方的包,名称:Stripe.net。
- 后端提供SessionId的代码如下
/// <summary> /// 调用stripe创建支付的会话,成功则返回会话的Id,用于页面跳转 /// </summary> /// <returns></returns> [HttpPost("create-checkout-session")] public ActionResult CreateCheckoutSession() { try { // Stripe的私钥,在 Stripe后台能看到 sk开头的,_test则表示是用于测试环境的。 StripeConfiguration.ApiKey = "sk_test_xxx"; //封装支付请求的数据, //字段说明详见官网:https://stripe.com/docs/api/checkout/sessions/object var options = new SessionCreateOptions { PaymentMethodTypes = new List<string> { "card" ,"alipay" //支持的付款方式 }, BillingAddressCollection= "required",//是否要收集帐单地址信息 LineItems = new List<SessionLineItemOptions> { new SessionLineItemOptions { PriceData = new SessionLineItemPriceDataOptions { UnitAmount = 2000, //需要支付的金额 Currency = "usd",//支持的货币简写,具体见官网 ProductData = new SessionLineItemPriceDataProductDataOptions { Name = "支付的显示名称,或者是商品名称", Images= new List<string>(){"https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png" }, Description="支付的描述信息,可以是商品的描述等信息" }, }, Quantity = 1, }, }, Mode = "payment", SuccessUrl = "https://example.com/success", //支付成功以后跳转的URL地址 CancelUrl = "https://example.com/cancel",//用户取消支付以后跳转的URL地址 }; options.PaymentIntentData = new SessionPaymentIntentDataOptions(); options.PaymentIntentData.Metadata = new Dictionary<string, string> { { "sn", "6735" }, { "attachmentValue", "6735" }, //传递的自定义参数,回调通知的时候会原样返回 }; var service = new SessionService(); Session session = service.Create(options); return Json(new { id = session.Id }); } catch (Exception ex) { throw ex; } }
- 上面前端HTML和后端的接口都处理好以后,点击页面上的那个去付款的按钮,则会跳转到Stripe的收银台页面(下图)。
- Stripe的测试也非常方便,官方提供了很多测试的卡号,下面表格是我收集整理的一些。卡号品牌CVC年月4242424242424242Visa任意3位数字大于当前时间的年月4000056655665556Visa (debit)任意3位数字大于当前时间的年月5555555555554444Mastercard任意3位数字大于当前时间的年月2223003122003222Mastercard (2-series)任意3位数字大于当前时间的年月5200828282828210Mastercard (debit)任意3位数字大于当前时间的年月5105105105105100Mastercard (prepaid)任意3位数字大于当前时间的年月378282246310005American Express任意4位数字大于当前时间的年月371449635398431American Express任意4位数字大于当前时间的年月6011111111111117Discover任意3位数字大于当前时间的年月6011000990139424Discover任意3位数字大于当前时间的年月3056930009020004Diners Club任意3位数字大于当前时间的年月36227206271667Diners Club (14 digit card)任意3位数字大于当前时间的年月3566002020360505JCB任意3位数字大于当前时间的年月6200000000000005UnionPay任意3位数字大于当前时间的年月
信用卡的年月,填写大于当前时间的年月即可。
- 在Stripe的支付页面填写好相关信息以后点击支付,如果没有问题的话就会支付成功。
- 支付成功以后可在Stripe的后台看到付款的金额和一些日志,日志包括事件、接口请求日志、订单数据等等。因为是测试的数据所以要先开启可查看测试数据,不然是看不到的,如何开启看下图。
- 完成上面的步骤以后,则发起支付收款简单的流程没有问题下,下面说下如何接受Stripe异步通知。
四:接受异步通知
- Stripe支持很多事件的通知,例如Session创建完成、订单付款完成、退款等等,详见官网说明。事件类型说明
- 需要一个HTTPS的接口,如果没有证书可去阿里云等申请免费的证书。Windows如何安装HTTPS证书?
- 在Stripe后台添加一个端点(接受通知的配置)见下图
- 事件类型非常多,目前我们是做跳转支付,支付成功了通知我们,则选择:payment_intent.succeeded 事件
- 拿到验证端点的密钥,每个端点有独立的密钥,见下图
- 编写接受通知的接口代码,官网有英文的说明代码,下面我把代码整理了贴出来。
/// <summary> /// 支付成功的异步通知接口 /// </summary> /// <returns></returns> [HttpPost] public async Task<IActionResult> Notify() { var json = new StreamReader(HttpContext.Request.Body).ReadToEndAsync().Result; try { //验证数据的来源 string endpointSecret = "whsec_XXXXX";//后台创建的端点签名密钥 var stripeEvent = EventUtility.ConstructEvent(json, Request.Headers["Stripe-Signature"], endpointSecret); //stripeEvent.Type 则是不同的事件,具体则看你配置端点的时候,这个接口设置了那些事件 if (stripeEvent.Type == Events.PaymentIntentSucceeded) { //支付成功的业务处理 var payModel = stripeEvent.Data.Object as PaymentIntent; decimal payAmount = payModel.Amount / 100M; //支付的金额 string payPaySN = payModel.Id;//支付方的唯一订单号 string payCurrency = payModel.Currency;//支付的货币 //账单信息,如果创建Session的时候设置收集账单信息,则这里可以获取到 var billing = payModel.Charges.Data[0].BillingDetails; string billingName = billing.Name; string billingEmail = billing.Email; string billingPhone = billing.Phone; string billingCity = billing.Address.City; string billingCountry = billing.Address.Country; string billingLine1 = billing.Address.Line1; string billingLine2 = billing.Address.Line2; string billingPostalCode = billing.Address.PostalCode; string billingState = billing.Address.State; //发起支付创建的自定义参数,这里具体根据自己的业务来 string orderSN = payModel.Metadata["sn"]; string attachmentValue = payModel.Metadata["attachmentValue"]; //其它的一些业务处理,比如更新订单状态等等 } else if (stripeEvent.Type == Events.PaymentMethodAttached) { var paymentMethod = stripeEvent.Data.Object as PaymentMethod; Console.WriteLine("PaymentMethod was attached to a Customer!"); } else { Console.WriteLine("Unhandled event type: {0}", stripeEvent.Type); } return Ok(); } catch (StripeException) { return BadRequest(); } }
- 完成上面的步骤,就可以测试发起支付了和接受支付结果了。
- Stripe后台可以看到请求的日志记录,可以针对端点发送测试数据,这些对于调试程序还是很方便的,具体如何使用我就不多说了,都是中文的大家用心看下就懂了。
- 上线的时候需要将相关配置参数换成正式环境的。
以上只是我们在研究Stripe支付的一点简单的总结,时间仓促很多细节还未深入说明。以上如有不正之处还望见谅,可给我留言讨论,谢谢!
发布者:IT柚子,转转请注明出处:https://ityouzi.com/archives/stripe-pay-code.html