JAVA实现的⽀付宝扫描⼆维码⽀付
⽀付项⽬采⽤springMvc+Dubbo架构实现,只对外提供接⼝何雯娜退出节目原因
原⽂地址:
前期酝酿准备
最近项⽬中要上线⽀付功能、前段时间刚开发完的扫码⽀付、不得不说开发团队的⽂档真是⼀个烂。但总算是对照着API把功能交付上线了。
前⼏天公司申请下来了企业⽀付宝,得空所以也把⽀付宝的扫码⽀付给集成进去。这⾥⼜不得不说,是⽀付宝的⽂档写的不咋地还是⾃⼰没有仔细阅读,总之翻遍了API最终在
沙箱⾥⾯运⾏成功(切记、认真读⽂档,不然各种BUG等着你)
什么是扫码⽀付?
扫码⽀付,指⽤户打开⽀付宝钱包中的“扫⼀扫”功能,扫描商家展⽰在某收银场景下的⼆维码并进⾏⽀付的模式。该模式适⽤于线下实体店⽀付、⾯对⾯⽀付等场景。
业务流程:
使⽤步骤:
⽤户登陆⽀付宝钱包,点击⾸页“付款-扫码付”,进⼊扫⼀扫界⾯;
收银员在商家收银系统操作⽣成⽀付宝订单,⽤户确认⽀付⾦额,并⽣成⼆维码;
⽤户使⽤钱包的“扫码付”,扫收银员提供的⼆维码,确认⽀付;
⽤户付款后商家收银系统会拿到⽀付成功或者失败的结果。
前⾯的⼤家可以⼤体了解⼀下
(这⾥选择JAVA版本)、点击下载、⾥⾯有详细的API测试⽅法。
如何集成到项⽬中去?
下载DEMO解压、仔细阅读⾥⾯的⽂件、⾥⾯有详细的项⽬结构。
参数配置zfbinfo.properties(沙箱环境⽹关参数不同)
1. # ⽀付宝⽹关名、partnerId和appId
2. #open_api_domain = openapi.alipay/gateway.do
黄子韬的女朋友3. #⽀付宝沙箱环境
4. open_api_domain = openapi.alipaydev/gateway.do
5. mcloud_api_domain = mcloudmonitor/gateway.do
6. pid = 此处请填写你的PID
7. appid = 此处请填写你当⾯付的APPID
8.
9. # RSA私钥、公钥和⽀付宝公钥
10. private_key = 此处请填写你的商户私钥且转PKCS8格式
11. public_key = 此处请填写你的商户公钥
12. alipay_public_key =
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDI6d306Q8fIfCOaTXyiUeJHkrIvYISRcc73s3vF1ZT7XN8RNPwJxo8pWaJMmvyTn9N4HQ632qJBVHf8sxHi/fEsraprwCtzvzQETrNRwVxLO5jVmRGi60j8Ue1efIlzPXV
尹恩惠 金钟国13.
14. # 当⾯付最⼤查询次数和查询间隔(毫秒)
15. max_query_retry = 5
16. query_duration = 5000
刘雯资料17.
18. # 当⾯付最⼤撤销次数和撤销间隔(毫秒)
19. max_cancel_retry = 3
20. cancel_duration = 2000
21.
22. # 交易保障线程第⼀次调度延迟和调度间隔(秒)
23. heartbeat_delay = 5
24. heartbeat_duration = 900
RSA私钥、公钥和⽀付宝公钥获取⽅法。
这⾥我选择的是⽅式⼀,使⽤⽀付宝提供的⼀键⽣成⼯具(内附使⽤说明)。
如果是JAVA程序public_key参数对应rsa_private_key_pkcs8.pem⽂件⾥⾯的内容,
public_key参数对⽤rsa_public_key.pem⽂件⾥⾯的内容。然后把公钥复制到沙箱中的RSA(SHA1)密钥中⽣成⽀付宝公钥、对应的是alipay_public_key参数。
如何⽣成⼆维码订单?
然后你就可以运⾏Main.java 中的额main⽅法进⾏测试了,运⾏结果如下:
1. [acts_pay]|2016-11-04 15:23:35:530|Configs{⽀付宝openapi⽹关: openapi.alipaydev/gateway.do
2. , ⽀付宝mcloudapi⽹关域名: mcloudmonitor/gateway.do
3. , pid: 2088102169116018
4. , appid: 2016073000123724
5. , 商户RSA私钥: MIICdw******rLZis=
6. , 商户RSA公钥: MIGfMA******IDAQAB
7. , ⽀付宝RSA公钥: MIGfMA******IDAQAB
8. , 查询重试次数: 5
9. , 查询间隔(毫秒): 5000
10. , 撤销尝试次数: 3
11. , 撤销重试间隔(毫秒): 2000
12. , 交易保障调度延迟(秒): 5
13. , 交易保障调度间隔(秒): 900
14. }
15. [acts_pay]|2016-11-04 15:23:35:719|trade.precreate bizContent:
{"out_trade_no":"tradeprecreate14782442155652020005","seller_id":"","total_amount":"0.01","undiscountable_amount":"0","subject":"xxx品牌xxx门店当⾯付扫码消费","body":"购买商品3件共
20.00元","goods_detail":[{"goods_id":"goods_id001","goods_name":"xxx⼩⾯包","quantity":1,"price":"10"},{"goods_id":"goods_id002","goods_name":"xxx⽛
刷","quantity":2,"price":"5"}],"operator_id":"test_operator_id","store_id":"test_store_id","extend_params":{"sys_service_provider_id":"2088100200300400500"}}
16. [acts_pay]|2016-11-04 15:23:37:875|{"alipay_trade_precreate_response":
{"code":"10000","msg":"Success","out_trade_no":"tradeprecreate14782442155652020005","qr_code":"https:\/\/qr.alipay\/bax03938xgzra2b5pijd00d2"},"sign":"LA2d5txq43c3t12sCsNEEGvu3plXUrqrd/uyzOy4HIMM5
17. [acts_pay]|2016-11-04 15:23:37:878|⽀付宝预下单成功: )
18. [acts_pay]|2016-11-04 15:23:37:878|code:10000, msg:Success
19. [acts_pay]|2016-11-04 15:23:37:878|body:{"alipay_trade_precreate_response":
{"code":"10000","msg":"Success","out_trade_no":"tradeprecreate14782442155652020005","qr_code":"https:\/\/qr.alipay\/bax03938xgzra2b5pijd00d2"},"sign":"LA2d5txq43c3t12sCsNEEGvu3plXUrqrd/uyzOy4HIMM5 20. [acts_pay]|2016-11-04 15:23:37:878|filePath:D:\qr.png
最后下载沙箱钱包就可以完成⼿机⽀付了。
如何实现异步通知?
⽤户会⽤⼿机扫码给⽀付宝付款,然后⽀付宝收到之后会发送⼀条⽀付成功的消息给我们设置的notify_url
1. import java.io.BufferedOutputStream;
2. import java.util.Enumeration;
3. import java.util.HashMap;
4. import java.util.Map;
5.
6. import javax.servlet.http.HttpServletRequest;
7. import javax.servlet.http.HttpServletResponse;
8.
9. import org.springframework.beans.factory.annotation.Autowired;
10. import org.springframework.stereotype.Controller;
11. import org.springframework.web.bind.annotation.RequestMapping;
12. import org.springframework.web.bind.annotation.RequestMethod;
13.
14. import com.acts.web.acc.service.IWeixinPayService;
15. import com.acts.webmon.utils.LogUtil;
16. import com.alipay.api.AlipayApiException;
17. import com.alipay.api.internal.util.AlipaySignature;
18. import com.fig.Configs;
19.
20. @Controller
21. @RequestMapping(value ="alipay")
22. public class AliPayController{
23. //初始化参数不然signVerified会验证失败
24. static{
25. Configs.init("zfbinfo.properties");
26. }
27. /**
28. * ⽀付宝⽀付回调
29. * @Author ⼩柒
30. * @param request
31. * @param response
32. * @throws Exception
33. * void
34. * @Date 2016年10⽉31⽇更新⽇志 2016年10⽉31⽇⼩柒⾸次创建
35. *
36. */
37. @SuppressWarnings("unchecked")
38. @RequestMapping(value ="pay",method =RequestMethod.POST)
39. public void alipay_notify(HttpServletRequest request,HttpServletResponse response)throws Exception{
40. LogUtil.info("⽀付宝付款异步通知!");
41. String message ="success";
42. Map<String,String> params =new HashMap<String,String>();
43. // 取出所有参数是为了验证签名
44. Enumeration<String> parameterNames = ParameterNames();
45. while(parameterNames.hasMoreElements()){
46. String parameterName = Element();
47. params.put(parameterName, Parameter(parameterName));
48. }
49. //验证签名
肖央的老婆50. boolean signVerified =false;
51. try{
52. signVerified =AlipaySignature.rsaCheckV1(AlipayPublicKey(),"UTF-8");
53. }catch(AlipayApiException e){
54. e.printStackTrace();
55. message ="failed";
56. }
57. if(signVerified){
58. LogUtil.info("验证签名成功!");
59. // 若参数中的appid和填⼊的appid不相同,则为异常通知
60. if(!Appid().("app_id"))){
61. LogUtil.info("与付款时的appid不同,此为异常通知,应忽略!");
62. message ="failed";
关于党的名言简短63. }else{
64. String outtradeno = ("out_trade_no");
65. LogUtil.info(outtradeno +"号订单回调通知。");
66.
67. //在数据库中查订单号对应的订单,并将其⾦额与数据库中的⾦额对⽐,若对不上,也为异常通知
68.
69. String status = ("trade_status");
70. if(status.equals("WAIT_BUYER_PAY")){// 如果状态是正在等待⽤户付款
71.
72. }else if(status.equals("TRADE_CLOSED")){// 如果状态是未付款交易超时关闭,或⽀付完成后全额退款
73.
74. }else if(status.equals("TRADE_SUCCESS")|| status.equals("TRADE_FINISHED")){// 如果状态是已经⽀付成功
75. //成功更新状态
76. }else{
77. weixinpayBack.updateAccOrder(outtradeno);
78. }
79. LogUtil.info(outtradeno +"订单的状态已经修改为"+ status);
80. }
81. }else{// 如果验证签名没有通过
82. message ="failed";
83. LogUtil.info("验证签名失败!");
84. }
85. BufferedOutputStream out =new OutputStream());
86. out.Bytes());
87. out.flush();
88. out.close();
89. }
90. }
91.
发布评论