求助:这张GIF的效果动图整了一个多小时,没找到好的编辑软件,都太难用了。如果恰巧看到这篇文章有好的GIF编辑或者录制软件,请推荐一 个!万谢
订单支付功能是购物的最后一个环节,本文将通过对接支付宝的接口,实现支付宝付款功能。蚂蚁金服开放平台专门为开发者的网站,包含了支付宝中涉及的很多功能接口,本文的功能实现是在沙箱环境中进行,蚂蚁沙箱环境(Beta)是协助开发者进行接口功能开发及主要功能联调的辅助环境。沙箱环境模拟了开放平台部分产品的主要功能和主要逻辑。在开发者应用上线审核前,开发者可以根据自身需求,先在沙箱环境中了解、组合和调试各种开放接口,进行开发调通工作,从而帮助开发者在应用上线审核完成后,能更快速、更顺利的进行线上调试和验收工作。
开发文档中给出了电脑支付接口的过程图
一、配置密钥
下载SDK
为了帮助开发者调用开放接口,提供了开放平台服务端SDK,包含JAVA、PHP和.NET三个语言版本,封装了签名&验签、HTTP接口请求等基础功能。但是支付宝没有提供Python的SDK,我们使用GitHub中的Python工具包(链接中有Python具体的实现方式),SDK的作用就是为了减少生成签名时容易出错,安装Python-Alipay-SDK在doc中输入pip install python-alipay --upgrade
开发者调用接口前需要先生成RSA密钥,RSA密钥包含应用私钥(APP_PRIVATE_KEY)、应用公钥(APP_PUBLIC_KEY)。生成密钥后在开放平台管理中心进行密钥配置,配置完成后可以获取支付宝公钥(ALIPAY_PUBLIC_KEY)。
生成密钥文件
openssl
只听到从知秋君办公室传来知秋君的声音: 我醉君复乐,陶然共忘机。有谁来对上联或下联?
此代码由一叶知秋网-知秋君整理
OpenSSL> genrsa -out app_private_key.pem 2048 # 私钥
OpenSSL> rsa -in app_private_key.pem -pubout -out app_public_key.pem # 导出公钥
此代码由一叶知秋网-知秋君整理将app_public_key中的内容复制到沙箱应用中
OpenSSL>exit
将刚刚生成的私钥和支付宝公钥放到项目目录下。
二、搭建和配置开发环境
调用接口
支付接口(alipay.trade.page.pay):
- 商户系统请求支付宝接口alipay.trade.page.pay,支付宝对商户请求参数进行校验,而后重定向至用户登录页面。
- 用户确认支付后,支付宝get请求returnUrl(商户入参传入),返回同步返回参数。
- 交易成功后,支付宝post请求notifyUrl(商户入参传入),返回异步通知参数。
- 若由于网络等问题异步通知没有到达,商户可自行调用alipay.trade.query接口进行查询,根据查询接口获取交易以及支付信息(商户也可以直接调用查询接口,不需要依赖异步通知)。
视图中的处理函数
# post def order_pay(request): '''订单支付''' # 用户登录判断 if not request.session.has_key('islogin'): return JsonResponse({'res':0, 'errmsg':'用户未登录'}) # 接收订单id order_id = request.POST.get('order_id') # 数据校验 if not order_id: return JsonResponse({'res':1, 'errmsg':'订单不存在'}) try: order = OrderInfo.objects.get(order_id=order_id, status=1, pay_method=3) except OrderInfo.DoesNotExist: return JsonResponse({'res':2, 'errmsg':'订单信息出错'}) # 和支付宝进行交互 alipay = AliPay( appid="64202", # 应用id app_notify_url=None, # 默认回调url app_private_key_path=os.path.join(settings.BASE_DIR, 'df_order/app_private_key.pem'), alipay_public_key_path=os.path.join(settings.BASE_DIR, 'df_order/alipay_public_key.pem'), # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥, sign_type = "RSA2", # RSA 或者 RSA2 debug = True, # 默认False ) # 电脑网站支付,需要跳转到https://openapi.alipaydev.com/gateway.do? + order_string total_pay = order.total_price + order.transit_price # decimal order_string = alipay.api_alipay_trade_page_pay( out_trade_no=order_id, # 订单id total_amount=str(total_pay), subject='天天生鲜%s'%order_id, return_url=None, notify_url=None # 可选, 不填则使用默认notify url ) # 返回应答 pay_url = settings.ALIPAY_URL + '?' + order_string return JsonResponse({'res':3, 'pay_url':pay_url, 'message':'OK'})
将支付结果通过查询接口返回
# post def check_pay(request): '''获取用户支付的结果''' # 用户登录判断 if not request.session.has_key('islogin'): return JsonResponse({'res': 0, 'errmsg': '用户未登录'}) passport_id = request.session.get('passport_id') # 接收订单id order_id = request.POST.get('order_id') # 数据校验 if not order_id: return JsonResponse({'res': 1, 'errmsg': '订单不存在'}) try: order = OrderInfo.objects.get(order_id=order_id, passport_id=passport_id, pay_method=3) except OrderInfo.DoesNotExist: return JsonResponse({'res': 2, 'errmsg': '订单信息出错'}) # 和支付宝进行交互 alipay = AliPay( appid="64202", # 应用id app_notify_url=None, # 默认回调url app_private_key_path=os.path.join(settings.BASE_DIR, 'df_order/app_private_key.pem'), alipay_public_key_path=os.path.join(settings.BASE_DIR, 'df_order/alipay_public_key.pem'), # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥, sign_type="RSA2", # RSA 或者 RSA2 debug=True, # 默认False ) while True: # 进行支付结果查询 result = alipay.api_alipay_trade_query(order_id) code = result.get('code') if code == '10000' and result.get('trade_status') == 'TRADE_SUCCESS': # 用户支付成功 # 改变订单支付状态 order.status = 2 # 待发货 # 填写支付宝交易号 order.trade_id = result.get('trade_no') order.save() # 返回数据 return JsonResponse({'res':3, 'message':'支付成功'}) elif code == '40004' or (code == '10000' and result.get('trade_status') == 'WAIT_BUYER_PAY'): # 支付订单还未生成,继续查询 # 用户还未完成支付,继续查询 time.sleep(5) continue else: # 支付出错 return JsonResponse({'res':4, 'errmsg':'支付出错'})
前端的post提交
<script> $(function () { $('.oper_btn').click(function () { // 获取订单id和订单的状态 order_id = $(this).attr('order_id') order_status = $(this).attr('order_status') //attr获取自定义的选择器 csrf = $('input[name="csrfmiddlewaretoken"]').val() //csrf防御 params = {'order_id':order_id, 'csrfmiddlewaretoken':csrf} if (order_status == 1){ $.post('/order/pay/', params, function (data) { if (data.res == 3){ // 把用户引导支付页面 window.open(data.pay_url) // 查询用户的支付结果 $.post('/order/check_pay/', params, function (data) { if (data.res == 3){ alert('支付成功') // 重新刷新页面 location.reload() } else{ alert(data.errmsg) } }) } else{ alert(data.errmsg) } }) } }) }) </script>
在setting配置alipay的沙箱网址URL
ALIPAY_URL='https://openapi.alipaydev.com/gateway.do'
总结:支付的过程其实大部分都是支付宝内部封装好的功能完成,我们只是调用了支付和查询接口,将参数通过接口传递进去,我们不需要知道支付宝内部怎么实现,就完成了支付收付款的功能。除了支付接口,支付宝还提供了很多免费的接口,如店铺、芝麻信用、生活服务等,通过这些接口我们可以做很多功能的实现,接口和文档链接:点击打开链接、点击打开链接