最近一个国外的电商项目,需要对接支付功能,国内的支付一般使用微信支付、支付宝、银联等等,但国际上一般使用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文件和点击跳转到支付按钮。当然支付的页面上还有很多其他的一些东西,比如收货地址、商品信息等等。
-
12345678910111213141516171819202122232425262728293031323334353637383940414243444546<!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的代码如下
-
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162/// <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/objectvar 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 事件
- 拿到验证端点的密钥,每个端点有独立的密钥,见下图
- 编写接受通知的接口代码,官网有英文的说明代码,下面我把代码整理了贴出来。
-
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061/// <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支付的一点简单的总结,时间仓促很多细节还未深入说明。以上如有不正之处还望见谅,可给我留言讨论,谢谢!
发布者:柚子,转转请注明出处:https://ityouzi.com/archives/stripe-pay-code.html
评论列表(3条)
异步通知需要在官网配置吗
需要在支付平台的后台配置,详见文章里面有说明。
大佬可否给个联系方式,最近在做stripe支付想请教下你一些事