一、一些名词解释:

1.1 对称加密:

image.png

1.2 非对称加密:

image.png

1.3 内网穿透:

image.png
image.png
image.png

1.4 内网穿透配置:

  1. listen 80;
  2. server_name zeyigou.com *.zeyigou.com 497n86m7k7.52http.net;
  3. #charset koi8-r;
  4. #access_log /var/log/nginx/log/host.access.log main;
  5. location /static/ {
  6. root /usr/share/nginx/html;
  7. }
  8. location /payed/ {
  9. proxy_set_header Host order.zeyigou.com;
  10. proxy_pass http://zeyigou;
  11. }

1.5 加签与验签:

image.png

1.6 收单:

1、订单在支付页,不支付,一直刷新,订单过期了才支付,订单状态改为已支付了,但是库存解锁了。

  • 使用支付宝自动收单功能解决。只要一段时间不支付,就不能支付了。

    2、由于时延等问题。订单解锁完成,正在解锁库存的时候,异步通知才到

  • 订单解锁,手动调用收单

3、网络阻塞问题,订单支付成功的异步通知一直不到达

  • 查询订单列表时,ajax获取当前未支付的订单状态,查询订单状态时,再获取一下支付宝此订单的状态

4、其他各种问题

  • 每天晚上闲时下载支付宝对账单,一一进行对账

二、支付宝沙箱使用:

2.0 支付宝支付时序图:

第十七章 订单支付 - 图7

2.1 使用沙箱开发一般步骤:

2.1.1 进入支付宝开发平台:

支付宝开放平台

2.1.2 进入[研发服务]

image.png

2.1.3 看到如下沙箱应用:

image.png

2.1.4 点击”设置/查看”:

image.png
image.png

2.1.5 进入下载页面下载并安装:

image.png

2.2.6 打开密钥生成工具如下:

image.png
image.png
image.png

2.2.7 复制应用私钥与支付宝公钥,后面开发中会用到。

2.2 下载官方SDK,并使用idea或Eclipse打开它

2.2.1 下载官方SDK:

下载地址
image.png

2.2.2 打开后的目录结构:[Eclipse目录结构]

image.png

说明: 如果是Idea打开,需要经过处理,以Eclipse导入后,指定Facets中的web文件件位置,删除原来的Eclipse的jar包,添加tomcat及当前项目中的jar包(WEB-INF/lib目录).

2.2.3 打开后的目录结构:[Idea目录结构]

image.png
引入的依赖:

  1. <parent>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-parent</artifactId>
  4. <version>2.4.0</version>
  5. </parent>
  6. <dependencies>
  7. <dependency>
  8. <groupId>com.alipay.sdk</groupId>
  9. <artifactId>alipay-sdk-java</artifactId>
  10. <version>4.16.2.ALL</version>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.springframework.boot</groupId>
  14. <artifactId>spring-boot-starter-web</artifactId>
  15. </dependency>
  16. <dependency>
  17. <groupId>org.projectlombok</groupId>
  18. <artifactId>lombok</artifactId>
  19. </dependency>
  20. </dependencies>

AlipayTemplate.java

  1. @Component
  2. @Data
  3. public class AlipayTemplate {
  4. //在支付宝创建的应用的id
  5. private String app_id = "2016110200786382";
  6. // 商户私钥,您的PKCS8格式RSA2私钥
  7. private String merchant_private_key = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCLNeHUbXVv6LRgV4NRyx4yH3dCBuXQLh/kzJmYlXjwkqXMNssDOvvQlT2Y5Pdws936IJSveNK9ViGurn9a8PwLyRTVazZFyDmb3v99E1qsGG9dCeZxL+ofPSsH8uS+E3det7MkAjQc3mxvL1bkoan/9N5zaxkqAn25Yy0sMTDdPE4Db1Y8u0p9WZQ0TniH5EW7vRCJHxV3SRBvCqiNoEOgIDAcmnIymD8OaSeUVAuj+Uiq1C15F270UxCPYzcME9Klbl53ifweBhSGUBDsHI12v7QOw6n1pVmX4OagNfLoALnM/MwZrpEnfUip/CD9UDrHMpN/oJpphzVd63sqclJjAgMBAAECggEAHAarAmNPA0qsFcFIlMz5tUmUbtyIo9LFZQCz434kLPq5GlXlpS7Yx3NkRUXDcxMjG1o31OPUOX3/pfVHen2NoKnI4faFpKLcxj6s3Pdqh78bnHWDyUHGNqfP4/fIiWPN4mnFTPiMmUtGNVQogDrzyK35ou7q0ARUX2BSFdWJauCNRA6LEap4LUWtF0N0vCryPeBcElUAYd3J/VhQM5NkBKBkCbvLE1S9cElBURLxJtus2KZvxWnryDxN3Pm3+YWRm9J/zXe6zBy1VHqXYRey4rtxWJWSzz7aZ8lPRZbwSedVr2cte3+CeQejYF744wDbyaHaiQ+6sU3ixmke4ACegQKBgQDr5cu8TWNfmslHTuDrcUgn5FkTSB5UuJJ58+EvpiEfVj9BK9nvniNFHAVEwLclhbAlAlLlDzu9U1Gx50E858G3YX11ETnBNV7sv/JjXZnMhOHy2IM5sm/hFobvqgqyPqTDDV6uVEhOutO1TLnIAMv21mQ77o067xezwP03WS1TIQKBgQCXEtDngMujfOVk0it3IbbiagZkMQh2GultA8pUd9KA/qB26Z1z95vORU3aKqYNeJHxtY69fh7hvqat6V93JjE3X1XuBKYj8GKE7INmUN3elXbDbF4ZAwf1aGeuaqi2kz9VV5A07MSOtKT9G/FWCaNLYbyuqtZgHi8CjtiqAmg5AwKBgGkL663uyFHKm9clSQOPbpJVHVV4yAjyKEgmUiDl2doajhB3dpU91nbwA2iaaPRMlCPm5QMbxX6Jm9edI2/7xEflIfj/srhXC+5hi460H8jzY6rAv67xxuB1J6GSFzFItBYn3gHDhm+Iwr35bMGjmTBSSFBn6nxT/DoPtrLvA0ABAoGANGV4QvKurjNBNGiYXqc40OpI8TL4Zk4LK54m7IjqX4bwjI2V6IS2ayIqUEJ+eSmaJKT9rscxWsZO9P5998stQrE0EmtWXByhbszA/hmJ+gsIt9q8ABzHA9yEKUAg58HGM4k9IL4FpiENICQy3c5V7m0ljcb+tzOAxnhYuQ5Aq5UCgYAooWmzBRcn/dajfawzZ9WOcAcJlq2+7TtL1SCU/wMg+LDhAuktXaVF7ZTuT8VUwYXX2pj12by/B0bWBCAhzlqUYQCII4wwbZq2f8nC/lbQfEisYVfcPQBYJA3pcAH+FCWUtIZMPhekniywNW2s+Ibrm2Sr6HIQA4dPFc27uH4N0g==";
  8. // 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
  9. private String alipay_public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr1mPk6rIzSaYkaOthD0zsivN4pln2o66yP1DdIuauV6ggAC6jkO7kfZHJmBYXY/oGXPSbWqdn2g8s6FHJzLAjT9XMOqhFtQh5mMCTr5/gdgN6oc9O/zYCD1xEV9pAXZ1rBufzXixjmlnA8lCNiLsRUcYjoAcUyDBPUP3iLTvFJm1XhmA3ogR5U2CR56wynIa+toaCLxEav9S6gkjALmLwFSkimySEUZB361f+kXCcO+riZwsO65uquXEH8p7z44hezkqT09kaEIQDAHXH6f/RhOzmAuNQHSD93DbzvjrWPyW2vYA/eQnPLNc+ctka/Nf6CH5X4XMfmp9q+4p19URcQIDAQAB";
  10. // 服务器[异步通知]页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
  11. // 支付宝会悄悄的给我们发送一个请求,告诉我们支付成功的信息
  12. private String notify_url = "http://localhost:8000/payed/notify";
  13. // 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
  14. //同步通知,支付成功,一般跳转到成功页
  15. private String return_url = "http://localhost:8000/memberOrder.html";
  16. // 签名方式
  17. private String sign_type = "RSA2";
  18. // 字符编码格式
  19. private String charset = "utf-8";
  20. private String timeout = "30m";
  21. // 支付宝网关; https://openapi.alipaydev.com/gateway.do
  22. private String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";
  23. public String pay(PayVo vo) throws AlipayApiException {
  24. //AlipayClient alipayClient = new DefaultAlipayClient(AlipayTemplate.gatewayUrl, AlipayTemplate.app_id, AlipayTemplate.merchant_private_key, "json", AlipayTemplate.charset, AlipayTemplate.alipay_public_key, AlipayTemplate.sign_type);
  25. //1、根据支付宝的配置生成一个支付客户端
  26. AlipayClient alipayClient = new DefaultAlipayClient(gatewayUrl,
  27. app_id, merchant_private_key, "json",
  28. charset, alipay_public_key, sign_type);
  29. //2、创建一个支付请求 //设置请求参数
  30. AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
  31. alipayRequest.setReturnUrl(return_url);
  32. alipayRequest.setNotifyUrl(notify_url);
  33. //商户订单号,商户网站订单系统中唯一订单号,必填
  34. String out_trade_no = vo.getOut_trade_no();
  35. //付款金额,必填
  36. String total_amount = vo.getTotal_amount();
  37. //订单名称,必填
  38. String subject = vo.getSubject();
  39. //商品描述,可空
  40. String body = vo.getBody();
  41. alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
  42. + "\"total_amount\":\""+ total_amount +"\","
  43. + "\"subject\":\""+ subject +"\","
  44. + "\"body\":\""+ body +"\","
  45. + "\"timeout_express\":\""+timeout+"\","
  46. + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
  47. String result = alipayClient.pageExecute(alipayRequest).getBody();
  48. //会收到支付宝的响应,响应的是一个页面,只要浏览器显示这个页面,就会自动来到支付宝的收银台页面
  49. System.out.println("支付宝的响应:"+result);
  50. return result;
  51. }
  52. }

PayVo.java(同步请求类)

  1. /**
  2. * ------------------------------
  3. * 功能:
  4. * 作者:WF
  5. * 微信:hbxfwf13590332912
  6. * 创建时间:2021/8/16-16:34
  7. * ------------------------------
  8. */
  9. @Data
  10. public class PayVo {
  11. private String out_trade_no; // 商户订单号 必填
  12. private String subject; // 订单名称 必填
  13. private String total_amount; // 付款金额 必填
  14. private String body; // 商品描述 可空
  15. }

PayAsyncVo.java (异步回调类)

  1. @ToString
  2. @Data
  3. public class PayAsyncVo {
  4. private String gmt_create;
  5. private String charset;
  6. private String gmt_payment;
  7. private Date notify_time;
  8. private String subject;
  9. private String sign;
  10. private String buyer_id;//支付者的id
  11. private String body;//订单的信息
  12. private String invoice_amount;//支付金额
  13. private String version;
  14. private String notify_id;//通知id
  15. private String fund_bill_list;
  16. private String notify_type;//通知类型; trade_status_sync
  17. private String out_trade_no;//订单号
  18. private String total_amount;//支付的总额
  19. private String trade_status;//交易状态 TRADE_SUCCESS
  20. private String trade_no;//流水号
  21. private String auth_app_id;//
  22. private String receipt_amount;//商家收到的款
  23. private String point_amount;//
  24. private String app_id;//应用id
  25. private String buyer_pay_amount;//最终支付的金额
  26. private String sign_type;//签名类型
  27. private String seller_id;//商家的id
  28. }

三、在项目中整合支付宝开发:

3.1 定义zyg-pay-interface工程,依赖如下:

  1. <dependencies>
  2. <dependency>
  3. <groupId>com.zelin</groupId>
  4. <artifactId>zyg-pojo</artifactId>
  5. <version>2.0</version>
  6. </dependency>
  7. </dependencies>

3.2 定义zyg-pay-service工程,依赖如下:

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-web</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>com.zelin</groupId>
  8. <artifactId>zyg-pay-interface</artifactId>
  9. <version>2.0</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>com.zelin</groupId>
  13. <artifactId>zyg-dao</artifactId>
  14. <version>2.0</version>
  15. </dependency>
  16. <!--1. 引入thymeleaf-->
  17. <dependency>
  18. <groupId>org.springframework.boot</groupId>
  19. <artifactId>spring-boot-starter-thymeleaf</artifactId>
  20. </dependency>
  21. <!--3.引入redis-->
  22. <dependency>
  23. <groupId>org.springframework.boot</groupId>
  24. <artifactId>spring-boot-starter-data-redis</artifactId>
  25. </dependency>
  26. <dependency>
  27. <groupId>com.alipay.sdk</groupId>
  28. <artifactId>alipay-sdk-java</artifactId>
  29. <version>4.16.2.ALL</version>
  30. </dependency>
  31. </dependencies>

3.3 zyg-pay-service的application.yml文件配置如下:

  1. server:
  2. port: 7008
  3. logging:
  4. level:
  5. com.zelin: debug
  6. spring:
  7. dubbo:
  8. application:
  9. name: zyg-pay-service
  10. registry:
  11. address: zookeeper://192.168.56.10:2181
  12. base-package: com.zelin.pay.service
  13. protocol:
  14. name: dubbo
  15. port: 21888
  16. thymeleaf:
  17. cache: false
  18. redis:
  19. host: 192.168.56.10
  20. alipay:
  21. app_id: 2016110200786382
  22. merchant_private_key: MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC5gxoY+/itsKQtamxVo5cgXS5qTrIYcEHv/vZ/hb3/B7+22HpcaYbD8JNoR2HXpzAYm9wizKPSup51u9JyUI6eEi2MfLxVI/FgwH/4rjM+U4Teq80WPeZFLqoimkOcwYV4ukwmOI8wBl3Tm5T243JlKSZYoB1o3g048aNRfv4/gS0zKOlpT+AFTbD8ceyhipamm48meZAg0s+MlgEGh+LABG53by1WI8V1VLZywUlhj20YdT6Hfdhg4t6cJUpjIxXOVi+K5UTeTy/KhSJqQ6Gp2b1rCuZ0/9WOCIvUKCCnMmcm52Z/IeTZZR5Im8Vwqm2S1AM2t4TFQQ+ZKUFQQRerAgMBAAECggEAKETPG3FGr91SJhGd5pEWMw5HDwh6HFfx2DjOJSxQ69Uwxm4DUaAOguXr+YzVLky6Yf0jMeKeBRZBY2kb63iVHLbxcDd7YjflI41lugOGWBclFnjQke1p2MaiY9R8rMBNSsGV2g4Y9uHK6C4zjcwdftwJ2N8YwzTARgYd34jjg8EV3mmkL8Qp+lK3q3kNdMm93WejlXbKBt4Adrr+LZHe8j+0gjp3vcRTeu8FBu+FiAXvLkNEIsg4jexwPrcPrHt2v761I4/EegLZqaYSyMFvfB72IsRaTaHeTjqBHuf0Dc6U1Kv5CV9R1rLgUdNC5bYix9xyPhtCV43QOmr1NEuNUQKBgQDmeqRMnYmRLbhEsS7MT7ql94hor+w7ekDSMUrjYlj/e8BBlVFf6KMza2yo3hp3nlZEOxo1HiNhCP2EZMIneO/Dy7aepQp5aQRKzzxy9ZcG6oJlaJlSdcCoB+d68h2HPAC6qg7VolLTNZYPHEfMYX+gX2X8EmcobmxJiidMMDIMBwKBgQDODcnGe8wt1IMRaio9eYYvG06WsoqaxCdl5UphL23l0eCBEOwi3WUx/lgzMQUti+EtZVr+XJIC6WMsBRXJMuqrY4T0Ar0aGezJC0S3+HefSkrQgqs3LZA6uw54eVyj5XEveGeY3Tv9fCJuSIQdds0S16sHosHd0XKhtEEgpq92PQKBgCXCeAJ5WN1pISRX5vPgKBMiz71e/RPtfosxOjSwmyYYLzJPdUqCQaKd+epcoPdyAG4jRLLpIiC2qVo0a76tyJJKYLvzDBlCBEsBUsT+yWR/rSdSELR6yDp/OQRigEX0paXvUIjdlDY4NEJ7fqPUYWVz27CFj1MHbERMFw4bY0enAoGAZGc3kK22GgbZLt0qY/YZOk72BlxNSYiXIgGOMrjntfqEiJ90ULDMpIWo+JjESyNDv9kJc7QruZt7pXF84iMbUhQWLsg+2L8VMAl7nKFHuKh8uAlT4HklNFj9fhq012/vrQ/gew4iMywPoulW5vyChNHuFrRp/uoWD1FEAuL10IkCgYABUXkMImvD3/xLUq75+rCHSr9TgVCC4CF+jEYqoy62ZNMUKvBXyjotAFQdJk4DfcmlBZQ7+EBZXW8cVt8i7xobvuOOzl93HAcnqnMNmw0UxWK9IX70/+9JdxYxHSLmRHWlBYf5gS9xlorhnBh+QLhaMeaNdUMeyCF/gTGUM6xJ2g==
  23. alipay_public_key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr1mPk6rIzSaYkaOthD0zsivN4pln2o66yP1DdIuauV6ggAC6jkO7kfZHJmBYXY/oGXPSbWqdn2g8s6FHJzLAjT9XMOqhFtQh5mMCTr5/gdgN6oc9O/zYCD1xEV9pAXZ1rBufzXixjmlnA8lCNiLsRUcYjoAcUyDBPUP3iLTvFJm1XhmA3ogR5U2CR56wynIa+toaCLxEav9S6gkjALmLwFSkimySEUZB361f+kXCcO+riZwsO65uquXEH8p7z44hezkqT09kaEIQDAHXH6f/RhOzmAuNQHSD93DbzvjrWPyW2vYA/eQnPLNc+ctka/Nf6CH5X4XMfmp9q+4p19URcQIDAQAB
  24. notify_url: http://42d323h910.qicp.vip/payed/notify
  25. return_url: http://cart.zeyigou.com/orderlist
  26. sign_type: RSA2
  27. charset: utf-8
  28. timeout: 30m
  29. gatewayUrl: https://openapi.alipaydev.com/gateway.do

说明app_id: 商户id merchant_private_key: 商户私钥 alipay_public_key: 支付宝公钥 notify_url: 支付成功后支付宝后台发送请求的异步回调地址,不要定义在cas这类单点登录的工程中。 return_url: 支付成功后立即跳转的地址。 sign_type:加密认证方式 timeout:代表关单时间,如:30m 即30分钟 gatewayUrl: 支付宝网关,固定值

3.4 在zyg-cart-web与zyg-page-web中分别引入zyg-pay-service:

  1. <!--引入支付服务-->
  2. <dependency>
  3. <groupId>com.zelin</groupId>
  4. <artifactId>zyg-pay-interface</artifactId>
  5. <version>2.0</version>
  6. </dependency>

注意: 最后,要进行异步调用,所以,我们不要把异步调用的方法写在zyg-cart-web这种有cas认证的模块中,否则,支付宝后台不能访问它。最后,异步调用会失败,所以,我们只需要定义一个没有cas认证的工程即可。

3.5 在zyg-cart-web中定义控制器如下:

  1. /**
  2. * ------------------------------
  3. * 功能:
  4. * 作者:WF
  5. * 微信:hbxfwf13590332912
  6. * 创建时间:2021/8/17-14:58
  7. * ------------------------------
  8. */
  9. @Controller
  10. public class PayController {
  11. @Reference(timeout = 5000)
  12. private PayService payService;
  13. @Reference(timeout = 5000)
  14. private OrderService orderService;
  15. /**
  16. * 功能: 点击支付页面中的支付宝按钮时行支付
  17. * 参数:
  18. * 返回值: java.lang.String
  19. * 时间: 2021/8/17 15:09
  20. */
  21. @RequestMapping("pay")
  22. @ResponseBody
  23. public String payOrder(String outTradeNo){
  24. //0. 得到登录id
  25. String name = SecurityContextHolder.getContext().getAuthentication().getName();
  26. //1. 根据支付订单号查询出payVo对象
  27. PayVo payVo = payService.findPayVoFromRedis(name,outTradeNo);
  28. //2. 调用支付方法
  29. String result = payService.pay(payVo);
  30. //3. 返回
  31. return result;
  32. }
  33. /**
  34. * 功能: 支付成功后跳转到的页面
  35. * 参数:
  36. * 返回值: java.lang.String
  37. * 时间: 2021/8/17 20:46
  38. */
  39. @RequestMapping("/orderlist")
  40. public String orderlist(Model model){
  41. //0. 得到登录id
  42. String name = SecurityContextHolder.getContext().getAuthentication().getName();
  43. //1. 根据登录用户id得到订单及订单项列表
  44. List<OrderEntity> orderEntities = orderService.findOrdersByUserId(name);
  45. //2. 放到model中到
  46. model.addAttribute("orderList",orderEntities);
  47. return "orderlist";
  48. }
  49. }

3.6 在zyg-page-web中定义回调监听器:

  1. /**
  2. * ------------------------------
  3. * 功能:
  4. * 作者:WF
  5. * 微信:hbxfwf13590332912
  6. * 创建时间:2021/8/17-16:44
  7. * ------------------------------
  8. */
  9. @RestController
  10. public class PaySyncController {
  11. @Reference(timeout = 5000)
  12. private PayService payService;
  13. /**
  14. * 功能: 支付宝发送异步通知
  15. * 参数:
  16. * 返回值: java.lang.String
  17. * 时间: 2021/8/17 16:46
  18. */
  19. @PostMapping("/payed/notify")
  20. public String payed(PayAsyncVo vo, HttpServletRequest request){
  21. System.out.println("vo = " + vo);
  22. //1. 得到登录用户
  23. //String userId = SecurityContextHolder.getContext().getAuthentication().getName();
  24. //2. 得支支付宝后台传入的数据
  25. Map<String,String> params = new HashMap<>();
  26. Map<String,String[]> requestParams = request.getParameterMap();
  27. for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
  28. String name = (String) iter.next();
  29. String[] values = (String[]) requestParams.get(name);
  30. String valueStr = "";
  31. for (int i = 0; i < values.length; i++) {
  32. valueStr = (i == values.length - 1) ? valueStr + values[i]
  33. : valueStr + values[i] + ",";
  34. }
  35. //乱码解决,这段代码在出现乱码时使用
  36. //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
  37. params.put(name, valueStr);
  38. }
  39. //boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type); //调用SDK验证签名
  40. String result = payService.payNotify(vo,params);
  41. System.out.println("result = " + result);
  42. return result;
  43. }
  44. }

zyg-page-web的application.yml文件中配置关于日期的格式, 不配置会报错!

  1. spring:
  2. mvc:
  3. date-format: yyyy-MM-dd HH:mm:ss

3.7 在zyg-order-service中添加方法的最后添加支付日志处理:

  1. /**
  2. * 功能: 提交订单
  3. * 参数:
  4. * 返回值: void
  5. * 时间: 2021/8/14 16:44
  6. */
  7. @Transactional
  8. @Override
  9. public void add(OrderEntity order) {
  10. //1. 得到购物车列表的字符串
  11. String cartStr = redisTemplate.opsForValue().get(order.getUserId());
  12. //2. 转换为List<Cart>对象并返回
  13. List<Cart> cartList = null;
  14. if(StringUtils.isNotBlank(cartStr)){
  15. cartList = JSON.parseArray(cartStr,Cart.class);
  16. }
  17. //2.1 定义代表所有订单的总金额
  18. double total = 0;
  19. //2.2 定义代表订单号的字符串
  20. String orderIds = "";
  21. //3. 添加订单(一个购物车对应一个订单)
  22. for (Cart cart : cartList) {
  23. //3.1 定义订单对象
  24. OrderEntity orderEntity = new OrderEntity();
  25. //3.2 生成订单id主键
  26. long id = idWorker.nextId();
  27. //累加订单和
  28. orderIds += id + ",";
  29. orderEntity.setOrderId(id);
  30. //3.3 设置订单的其它相关属性
  31. orderEntity.setCreateTime(new Date());
  32. orderEntity.setPaymentType(order.getPaymentType());
  33. orderEntity.setReceiver(order.getReceiver());
  34. orderEntity.setReceiverAreaName(order.getReceiverAreaName());
  35. orderEntity.setReceiverMobile(order.getReceiverMobile());
  36. orderEntity.setSellerId(cart.getSellerId());
  37. orderEntity.setUserId(order.getUserId());
  38. orderEntity.setSourceType(order.getSourceType());
  39. orderEntity.setStatus("1"); //未支付
  40. double sum = 0; //定义订单的总金额
  41. //3.4 得到购物车的购物项数据,向订单项表中添加此数据
  42. for (OrderItemEntity item : cart.getOrderItemList()) {
  43. //3.4.1 计算小计
  44. BigDecimal totalFee = new BigDecimal(item.getNum() * item.getPrice().doubleValue());
  45. item.setTotalFee(totalFee);
  46. //3.4.2 累加总金额
  47. sum += totalFee.doubleValue();
  48. //3.4.3 设置订单的id
  49. item.setOrderId(id);
  50. //3.4.4 设置订单项的id
  51. item.setId(idWorker.nextId());
  52. //3.4.5 设置商家id
  53. item.setSellerId(cart.getSellerId());
  54. //3.4.6 添加订单项到tb_ordeItem表
  55. orderItemDao.insert(item);
  56. }
  57. //3.5 计算此订单的总金额
  58. orderEntity.setPayment(new BigDecimal(sum));
  59. //3.6 添加订单
  60. this.save(orderEntity);
  61. //3.7 累加总金额
  62. total += sum;
  63. }
  64. //4. 保存支付日志到数据库
  65. if(order.getPaymentType().equals("1")){ //1:代表网上支付
  66. //4.1 定义支付日志
  67. PayLogEntity payLog = new PayLogEntity();
  68. payLog.setCreateTime(new Date());
  69. payLog.setPayType("2"); //代表支付宝
  70. payLog.setTradeState("0"); //代表未支付 0:未支付 1:己支付
  71. payLog.setUserId(order.getUserId()); //设置登录用户
  72. payLog.setOutTradeNo(idWorker.nextId()); //设置支付的订单号
  73. payLog.setTotalFee((long) (total)); //计算总金额
  74. payLog.setSubject("泽易购商城支付订单");
  75. payLog.setBody("一个良好的网上交易平台...");
  76. //4.2 去掉多余的订单id后的逗号
  77. orderIds = orderIds.substring(0, orderIds.length() - 1);
  78. //4.3 设置订单号
  79. payLog.setOrderList(orderIds);
  80. //4.4 添加支付日志到数据库中
  81. payLogDao.insert(payLog) ;
  82. //5. 保存到redis中一份(key:登录userid value:订单日志对象)
  83. redisTemplate.opsForValue().set(order.getUserId() + ":paylog",JSON.toJSONString(payLog),10, TimeUnit.DAYS);
  84. }
  85. //6. 清空redis中的购物车
  86. //todo...
  87. }

3.8 在zyg-pay-service中添加支付成功后对支付日志及订单的修改:

  1. /**
  2. * ------------------------------
  3. * 功能:
  4. * 作者:WF
  5. * 微信:hbxfwf13590332912
  6. * 创建时间:2021/8/17-15:05
  7. * ------------------------------
  8. */
  9. @Service
  10. public class PayServiceImpl extends ServiceImpl<PayLogDao, PayLogEntity> implements PayService {
  11. @Autowired
  12. private StringRedisTemplate redisTemplate;
  13. @Autowired
  14. private AlipayTemplate alipayTemplate;
  15. @Autowired
  16. private OrderDao orderDao;
  17. //1. 从redis中查询出订单日志
  18. @Override
  19. public PayLogEntity findPayLogByUserId(String name) {
  20. String s = redisTemplate.opsForValue().get(name + ":paylog");
  21. PayLogEntity payLogEntity = JSON.parseObject(s, PayLogEntity.class);
  22. return payLogEntity;
  23. }
  24. //2. 从redis中根据订单号查询payVo对象
  25. @Override
  26. public PayVo findPayVoFromRedis(String name, String tradeNo) {
  27. //2.1 查询出支付日志对象
  28. String s = redisTemplate.opsForValue().get(name + ":paylog");
  29. //2.2 转换为payLog
  30. PayLogEntity payLogEntity = JSON.parseObject(s, PayLogEntity.class);
  31. //2.3 定义payVo对象
  32. PayVo payVo = new PayVo();
  33. payVo.setBody(payLogEntity.getBody());
  34. payVo.setOut_trade_no(payLogEntity.getOutTradeNo() + "");
  35. payVo.setSubject(payLogEntity.getSubject());
  36. payVo.setTotal_amount(payLogEntity.getTotalFee() + "");
  37. //2.4 返回
  38. return payVo;
  39. }
  40. /**
  41. * 功能: 返回的是支付的表单 页面
  42. * 参数:
  43. * 返回值: java.lang.String
  44. * 时间: 2021/8/17 15:26
  45. */
  46. @Override
  47. public String pay(PayVo payVo) {
  48. try {
  49. return alipayTemplate.pay(payVo);
  50. } catch (AlipayApiException e) {
  51. e.printStackTrace();
  52. }
  53. return "hello";
  54. }
  55. /**
  56. * 功能: 验签并返回字符串,如果是success,就代表成功,否则,失败
  57. * 参数:
  58. * 返回值: java.lang.String
  59. * 时间: 2021/8/17 16:52
  60. */
  61. @Override
  62. public String payNotify(PayAsyncVo vo, Map<String, String> params) {
  63. try {
  64. //1. 进行验签
  65. boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayTemplate.getAlipay_public_key(),
  66. alipayTemplate.getCharset(), alipayTemplate.getSign_type()); //调用SDK验证签名
  67. //2. 判断是否验签成功
  68. if(signVerified){
  69. //第一部分:修改支付日志
  70. //2.1 更新支付日志与订单
  71. //String s = redisTemplate.opsForValue().get(userId + ":paylog");
  72. //PayLogEntity payLogEntity = JSON.parseObject(s, PayLogEntity.class);
  73. String out_trade_no = vo.getOut_trade_no();
  74. PayLogEntity payLogEntity = this.getById(out_trade_no);
  75. payLogEntity.setTransactionId(vo.getTrade_no());
  76. payLogEntity.setTradeState("1"); //代表己支付
  77. //2.2 修改到数据库中
  78. this.updateById(payLogEntity);
  79. //第二部分:修改订单的状态
  80. //2.1 得到订单id列表
  81. String orderList = payLogEntity.getOrderList();
  82. //2.2 使用,使用,号进行拆分
  83. String[] split = orderList.split(",");
  84. //2.3 遍历出每一个订单id
  85. for (String orderId : split) {
  86. //2.3.1 根据订单id查询出订单
  87. OrderEntity orderEntity = orderDao.selectById(orderId);
  88. //2.3.2 修改订单状态值
  89. orderEntity.setStatus("2"); //2:代表己付款
  90. //2.3.3 保存订单
  91. orderDao.updateById(orderEntity);
  92. }
  93. System.out.println("支付成功");
  94. return "success";
  95. }
  96. } catch (AlipayApiException e) {
  97. e.printStackTrace();
  98. }
  99. System.out.println("支付失败!");
  100. return "fail";
  101. }
  102. }

3.9 最终结果效果图:

image.png
image.png
image.png
image.png

四、内网穿透配置如下:

image.png