Browse Source

mall + pay:
1. 修复支付宝沙箱地址的调整
2. 收银台的前端 URL 支付走整个网页跳转
3. 收银台的支付成功后,增加 returnUrl 回跳
4. 修复 PayNotifyTask 首次通知时,可能会失败的情况;原因:租户未传递;

YunaiV 1 year ago
parent
commit
0ac599a3d9

+ 3 - 11
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPayClientConfig.java

@@ -18,15 +18,6 @@ import java.util.Set;
 @Data
 public class AlipayPayClientConfig implements PayClientConfig {
 
-    /**
-     * 网关地址 - 线上
-     */
-    public static final String SERVER_URL_PROD = "https://openapi.alipay.com/gateway.do";
-    /**
-     * 网关地址 - 沙箱
-     */
-    public static final String SERVER_URL_SANDBOX = "https://openapi.alipaydev.com/gateway.do";
-
     /**
      * 公钥类型 - 公钥模式
      */
@@ -43,8 +34,9 @@ public class AlipayPayClientConfig implements PayClientConfig {
 
     /**
      * 网关地址
-     * 1. {@link #SERVER_URL_PROD}
-     * 2. {@link #SERVER_URL_SANDBOX}
+     *
+     * 1. <a href="https://openapi.alipay.com/gateway.do">生产环境</a>
+     * 2. <a href="https://openapi-sandbox.dl.alipaydev.com/gateway.do">沙箱环境</a>
      */
     @NotBlank(message = "网关地址不能为空", groups = {ModePublicKey.class, ModeCertificate.class})
     private String serverUrl;

+ 4 - 2
yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImplIntegrationTest.java

@@ -24,6 +24,8 @@ import java.io.FileNotFoundException;
 @Disabled
 public class PayClientFactoryImplIntegrationTest {
 
+    private static final String SERVER_URL_SANDBOX = "https://openapi.alipaydev.com/gateway.do";
+
     private final PayClientFactoryImpl payClientFactory = new PayClientFactoryImpl();
 
     /**
@@ -79,7 +81,7 @@ public class PayClientFactoryImplIntegrationTest {
         // 创建配置
         AlipayPayClientConfig config = new AlipayPayClientConfig();
         config.setAppId("2021000118634035");
-        config.setServerUrl(AlipayPayClientConfig.SERVER_URL_SANDBOX);
+        config.setServerUrl(SERVER_URL_SANDBOX);
         config.setSignType(AlipayPayClientConfig.SIGN_TYPE_DEFAULT);
         config.setPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCHsEV1cDupwJv890x84qbppUtRIfhaKSwSVN0thCcsDCaAsGR5MZslDkO8NCT9V4r2SVXjyY7eJUZlZd1M0C8T01Tg4UOx5LUbic0O3A1uJMy6V1n9IyYwbAW3AEZhBd5bSbPgrqvmv3NeWSTQT6Anxnllf+2iDH6zyA2fPl7cYyQtbZoDJQFGqr4F+cGh2R6akzRKNoBkAeMYwoY6es2lX8sJxCVPWUmxNUoL3tScwlSpd7Bxw0q9c/X01jMwuQ0+Va358zgFiGERTE6yD01eu40OBDXOYO3z++y+TAYHlQQ2toMO63trepo88X3xV3R44/1DH+k2pAm2IF5ixiLrAgMBAAECggEAPx3SoXcseaD7rmcGcE0p4SMfbsUDdkUSmBBbtfF0GzwnqNLkWa+mgE0rWt9SmXngTQH97vByAYmLPl1s3G82ht1V7Sk7yQMe74lhFllr8eEyTjeVx3dTK1EEM4TwN+936DTXdFsr4TELJEcJJdD0KaxcCcfBLRDs2wnitEFZ9N+GoZybVmY8w0e0MI7PLObUZ2l0X4RurQnfG9ZxjXjC7PkeMVv7cGGylpNFi3BbvkRhdhLPDC2E6wqnr9e7zk+hiENivAezXrtxtwKovzCtnWJ1r0IO14Rh47H509Ic0wFnj+o5YyUL4LdmpL7yaaH6fM7zcSLFjNZPHvZCKPwYcQKBgQDQFho98QvnL8ex4v6cry4VitGpjSXm1qP3vmMQk4rTsn8iPWtcxPjqGEqOQJjdi4Mi0VZKQOLFwlH0kl95wNrD/isJ4O1yeYfX7YAXApzHqYNINzM79HemO3Yx1qLMW3okRFJ9pPRzbQ9qkTpsaegsmyX316zOBhzGRYjKbutTYwKBgQCm7phr9XdFW5Vh+XR90mVs483nrLmMiDKg7YKxSLJ8amiDjzPejCn7i95Hah08P+2MIZLIPbh2VLacczR6ltRRzN5bg5etFuqSgfkuHyxpoDmpjbe08+Q2h8JBYqcC5Nhv1AKU4iOUhVLHo/FBAQliMcGc/J3eiYTFC7EsNx382QKBgClb20doe7cttgFTXswBvaUmfFm45kmla924B7SpvrQpDD/f+VDtDZRp05fGmxuduSjYdtA3aVtpLiTwWu22OUUvZZqHDGruYOO4Hvdz23mL5b4ayqImCwoNU4bAZIc9v18p/UNf3/55NNE3oGcf/bev9rH2OjCQ4nM+Ktwhg8CFAoGACSgvbkShzUkv0ZcIf9ppu+ZnJh1AdGgINvGwaJ8vQ0nm/8h8NOoFZ4oNoGc+wU5Ubops7dUM6FjPR5e+OjdJ4E7Xp7d5O4J1TaIZlCEbo5OpdhaTDDcQvrkFu+Z4eN0qzj+YAKjDAOOrXc4tbr5q0FsgXscwtcNfaBuzFVTUrUkCgYEAwzPnMNhWG3zOWLUs2QFA2GP4Y+J8cpUYfj6pbKKzeLwyG9qBwF1NJpN8m+q9q7V9P2LY+9Lp9e1mGsGeqt5HMEA3P6vIpcqLJLqE/4PBLLRzfccTcmqb1m71+erxTRhHBRkGS+I7dZEb3olQfnS1Y1tpMBxiwYwR3LW4oXuJwj8=");
         config.setAlipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnq90KnF4dTnlzzmxpujbI05OYqi5WxAS6cL0gnZFv2gK51HExF8v/BaP7P979PhFMgWTqmOOI+Dtno5s+yD09XTY1WkshbLk6i4g2Xlr8fyW9ODnkU88RI2w9UdPhQU4cPPwBNlrsYhKkVK2OxwM3kFqjoBBY0CZoZCsSQ3LDH5WeZqPArlsS6xa2zqJBuuoKjMrdpELl3eXSjP8K54eDJCbeetCZNKWLL3DPahTPB7LZikfYmslb0QUvCgGapD0xkS7eVq70NaL1G57MWABs4tbfWgxike4Daj3EfUrzIVspQxj7w8HEj9WozJPgL88kSJSits0pqD3n5r8HSuseQIDAQAB");
@@ -103,7 +105,7 @@ public class PayClientFactoryImplIntegrationTest {
         // 创建配置
         AlipayPayClientConfig config = new AlipayPayClientConfig();
         config.setAppId("2021000118634035");
-        config.setServerUrl(AlipayPayClientConfig.SERVER_URL_SANDBOX);
+        config.setServerUrl(SERVER_URL_SANDBOX);
         config.setSignType(AlipayPayClientConfig.SIGN_TYPE_DEFAULT);
         config.setPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCHsEV1cDupwJv890x84qbppUtRIfhaKSwSVN0thCcsDCaAsGR5MZslDkO8NCT9V4r2SVXjyY7eJUZlZd1M0C8T01Tg4UOx5LUbic0O3A1uJMy6V1n9IyYwbAW3AEZhBd5bSbPgrqvmv3NeWSTQT6Anxnllf+2iDH6zyA2fPl7cYyQtbZoDJQFGqr4F+cGh2R6akzRKNoBkAeMYwoY6es2lX8sJxCVPWUmxNUoL3tScwlSpd7Bxw0q9c/X01jMwuQ0+Va358zgFiGERTE6yD01eu40OBDXOYO3z++y+TAYHlQQ2toMO63trepo88X3xV3R44/1DH+k2pAm2IF5ixiLrAgMBAAECggEAPx3SoXcseaD7rmcGcE0p4SMfbsUDdkUSmBBbtfF0GzwnqNLkWa+mgE0rWt9SmXngTQH97vByAYmLPl1s3G82ht1V7Sk7yQMe74lhFllr8eEyTjeVx3dTK1EEM4TwN+936DTXdFsr4TELJEcJJdD0KaxcCcfBLRDs2wnitEFZ9N+GoZybVmY8w0e0MI7PLObUZ2l0X4RurQnfG9ZxjXjC7PkeMVv7cGGylpNFi3BbvkRhdhLPDC2E6wqnr9e7zk+hiENivAezXrtxtwKovzCtnWJ1r0IO14Rh47H509Ic0wFnj+o5YyUL4LdmpL7yaaH6fM7zcSLFjNZPHvZCKPwYcQKBgQDQFho98QvnL8ex4v6cry4VitGpjSXm1qP3vmMQk4rTsn8iPWtcxPjqGEqOQJjdi4Mi0VZKQOLFwlH0kl95wNrD/isJ4O1yeYfX7YAXApzHqYNINzM79HemO3Yx1qLMW3okRFJ9pPRzbQ9qkTpsaegsmyX316zOBhzGRYjKbutTYwKBgQCm7phr9XdFW5Vh+XR90mVs483nrLmMiDKg7YKxSLJ8amiDjzPejCn7i95Hah08P+2MIZLIPbh2VLacczR6ltRRzN5bg5etFuqSgfkuHyxpoDmpjbe08+Q2h8JBYqcC5Nhv1AKU4iOUhVLHo/FBAQliMcGc/J3eiYTFC7EsNx382QKBgClb20doe7cttgFTXswBvaUmfFm45kmla924B7SpvrQpDD/f+VDtDZRp05fGmxuduSjYdtA3aVtpLiTwWu22OUUvZZqHDGruYOO4Hvdz23mL5b4ayqImCwoNU4bAZIc9v18p/UNf3/55NNE3oGcf/bev9rH2OjCQ4nM+Ktwhg8CFAoGACSgvbkShzUkv0ZcIf9ppu+ZnJh1AdGgINvGwaJ8vQ0nm/8h8NOoFZ4oNoGc+wU5Ubops7dUM6FjPR5e+OjdJ4E7Xp7d5O4J1TaIZlCEbo5OpdhaTDDcQvrkFu+Z4eN0qzj+YAKjDAOOrXc4tbr5q0FsgXscwtcNfaBuzFVTUrUkCgYEAwzPnMNhWG3zOWLUs2QFA2GP4Y+J8cpUYfj6pbKKzeLwyG9qBwF1NJpN8m+q9q7V9P2LY+9Lp9e1mGsGeqt5HMEA3P6vIpcqLJLqE/4PBLLRzfccTcmqb1m71+erxTRhHBRkGS+I7dZEb3olQfnS1Y1tpMBxiwYwR3LW4oXuJwj8=");
         config.setAlipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnq90KnF4dTnlzzmxpujbI05OYqi5WxAS6cL0gnZFv2gK51HExF8v/BaP7P979PhFMgWTqmOOI+Dtno5s+yD09XTY1WkshbLk6i4g2Xlr8fyW9ODnkU88RI2w9UdPhQU4cPPwBNlrsYhKkVK2OxwM3kFqjoBBY0CZoZCsSQ3LDH5WeZqPArlsS6xa2zqJBuuoKjMrdpELl3eXSjP8K54eDJCbeetCZNKWLL3DPahTPB7LZikfYmslb0QUvCgGapD0xkS7eVq70NaL1G57MWABs4tbfWgxike4Daj3EfUrzIVspQxj7w8HEj9WozJPgL88kSJSits0pqD3n5r8HSuseQIDAQAB");

+ 2 - 2
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/util/TenantUtils.java

@@ -82,9 +82,9 @@ public class TenantUtils {
      * 将多租户编号,添加到 header 中
      *
      * @param headers HTTP 请求 headers
+     * @param tenantId 租户编号
      */
-    public static void addTenantHeader(Map<String, String> headers) {
-        Long tenantId = TenantContextHolder.getTenantId();
+    public static void addTenantHeader(Map<String, String> headers, Long tenantId) {
         if (tenantId != null) {
             headers.put(HEADER_TENANT_ID, tenantId.toString());
         }

+ 2 - 2
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java

@@ -1,6 +1,6 @@
 package cn.iocoder.yudao.module.pay.dal.dataobject.notify;
 
-import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
 import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
 import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
@@ -25,7 +25,7 @@ import java.time.LocalDateTime;
 @Data
 @EqualsAndHashCode(callSuper = true)
 @Accessors(chain = true)
-public class PayNotifyTaskDO extends BaseDO {
+public class PayNotifyTaskDO extends TenantBaseDO {
 
     /**
      * 通知频率,单位为秒。

+ 15 - 18
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyServiceImpl.java

@@ -24,10 +24,11 @@ import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
 import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.context.annotation.Lazy;
-import org.springframework.scheduling.annotation.Async;
 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.support.TransactionSynchronization;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
 
 import javax.annotation.Resource;
 import javax.validation.Valid;
@@ -86,6 +87,7 @@ public class PayNotifyServiceImpl implements PayNotifyService {
     private PayNotifyServiceImpl self;
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void createPayNotifyTask(PayNotifyTaskCreateReqDTO reqDTO) {
         PayNotifyTaskDO task = new PayNotifyTaskDO();
         task.setType(reqDTO.getType()).setDataId(reqDTO.getDataId());
@@ -105,8 +107,13 @@ public class PayNotifyServiceImpl implements PayNotifyService {
         // 执行插入
         payNotifyTaskMapper.insert(task);
 
-        // 异步直接发起任务。虽然会有定时任务扫描,但是会导致延迟
-        self.executeNotifyAsync(task);
+        // 必须在事务提交后,在发起任务,否则 PayNotifyTaskDO 还没入库,就提前回调接入的业务
+        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
+            @Override
+            public void afterCommit() {
+                executeNotify(task);
+            }
+        });
     }
 
     @Override
@@ -121,7 +128,7 @@ public class PayNotifyServiceImpl implements PayNotifyService {
         CountDownLatch latch = new CountDownLatch(tasks.size());
         tasks.forEach(task -> threadPoolTaskExecutor.execute(() -> {
             try {
-                executeNotifySync(task);
+                executeNotify(task);
             } finally {
                 latch.countDown();
             }
@@ -150,22 +157,12 @@ public class PayNotifyServiceImpl implements PayNotifyService {
         log.error("[awaitExecuteNotify][任务未处理完,总任务数({}) 剩余任务数({})]", size, latch.getCount());
     }
 
-    /**
-     * 异步执行单个支付通知
-     *
-     * @param task 通知任务
-     */
-    @Async
-    public void executeNotifyAsync(PayNotifyTaskDO task) {
-        self.executeNotifySync(task); // 使用 self,避免事务不发起
-    }
-
     /**
      * 同步执行单个支付通知
      *
      * @param task 通知任务
      */
-    public void executeNotifySync(PayNotifyTaskDO task) {
+    public void executeNotify(PayNotifyTaskDO task) {
         // 分布式锁,避免并发问题
         payNotifyLockCoreRedisDAO.lock(task.getId(), NOTIFY_TIMEOUT_MILLIS, () -> {
             // 校验,当前任务是否已经被通知过
@@ -178,12 +175,12 @@ public class PayNotifyServiceImpl implements PayNotifyService {
             }
 
             // 执行通知
-            self.executeNotify(dbTask);
+            self.executeNotify0(dbTask);
         });
     }
 
     @Transactional
-    public void executeNotify(PayNotifyTaskDO task) {
+    public void executeNotify0(PayNotifyTaskDO task) {
         // 发起回调
         CommonResult<?> invokeResult = null;
         Throwable invokeException = null;
@@ -223,7 +220,7 @@ public class PayNotifyServiceImpl implements PayNotifyService {
         }
         // 拼接 header 参数
         Map<String, String> headers = new HashMap<>();
-        TenantUtils.addTenantHeader(headers);
+        TenantUtils.addTenantHeader(headers, task.getTenantId());
 
         // 发起请求
         try (HttpResponse response = HttpUtil.createPost(task.getNotifyUrl())

+ 4 - 3
yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceTest.java

@@ -33,6 +33,8 @@ import static org.junit.jupiter.api.Assertions.*;
 @Import({PayChannelServiceImpl.class})
 public class PayChannelServiceTest extends BaseDbUnitTest {
 
+    private static final String ALIPAY_SERVER_URL = "https://openapi.alipay.com/gateway.do";
+
     @Resource
     private PayChannelServiceImpl channelService;
 
@@ -106,7 +108,6 @@ public class PayChannelServiceTest extends BaseDbUnitTest {
         assertPojoEquals(reqVO, channel, "config");
         // 关于config 对象应该拿出来重新对比
         assertPojoEquals(payClientConfig, channel.getConfig());
-
     }
 
     @Test
@@ -291,7 +292,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest {
 
     public AlipayPayClientConfig getPublicKeyConfig() {
         return new AlipayPayClientConfig()
-                .setServerUrl(AlipayPayClientConfig.SERVER_URL_PROD)
+                .setServerUrl(ALIPAY_SERVER_URL)
                 .setAppId("APP00001")
                 .setSignType(AlipayPayClientConfig.SIGN_TYPE_DEFAULT)
                 .setMode(AlipayPayClientConfig.MODE_PUBLIC_KEY)
@@ -304,7 +305,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest {
 
     public AlipayPayClientConfig getCertificateConfig() {
         return new AlipayPayClientConfig()
-                .setServerUrl(AlipayPayClientConfig.SERVER_URL_PROD)
+                .setServerUrl(ALIPAY_SERVER_URL)
                 .setAppId("APP00001")
                 .setSignType(AlipayPayClientConfig.SIGN_TYPE_DEFAULT)
                 .setMode(AlipayPayClientConfig.MODE_CERTIFICATE)

+ 3 - 0
yudao-ui-admin/src/plugins/tab.js

@@ -36,6 +36,9 @@ export default {
         return router.push(lastPath || '/');
       });
     }
+    if (typeof obj === "function") {
+      return store.dispatch('tagsView/delView', router.currentRoute).then(obj);
+    }
     return store.dispatch('tagsView/delView', obj);
   },
   // 关闭所有tab页签

+ 4 - 4
yudao-ui-admin/src/views/pay/app/components/aliPayChannelForm.vue

@@ -41,17 +41,17 @@
           </el-radio-group>
         </el-form-item>
         <div v-if="form.aliPayConfig.mode === 1">
-          <el-form-item label-width="180px" label="商户私钥" prop="aliPayConfig.privateKey">
+          <el-form-item label-width="180px" label="应用私钥" prop="aliPayConfig.privateKey">
             <el-input type="textarea" :autosize="{minRows: 8, maxRows: 8}" v-model="form.aliPayConfig.privateKey"
-                      placeholder="请输入商户私钥" clearable :style="{width: '100%'}">
+                      placeholder="请输入应用私钥" clearable :style="{width: '100%'}">
             </el-input>
           </el-form-item>
-          <el-form-item label-width="180px" label="支付宝公钥字符串" prop="aliPayConfig.alipayPublicKey">
+          <el-form-item label-width="180px" label="支付宝公钥" prop="aliPayConfig.alipayPublicKey">
             <el-input
               type="textarea"
               :autosize="{minRows: 8, maxRows: 8}"
               v-model="form.aliPayConfig.alipayPublicKey"
-              placeholder="请输入支付宝公钥字符串" clearable
+              placeholder="请输入支付宝公钥" clearable
               :style="{width: '100%'}">
             </el-input>
           </el-form-item>

+ 44 - 112
yudao-ui-admin/src/views/pay/cashier/index.vue

@@ -48,15 +48,6 @@
       <qrcode-vue :value="qrCode.url" size="310" level="L" />
     </el-dialog>
 
-    <!-- 展示形式:IFrame -->
-    <el-dialog :title="iframe.title" :visible.sync="iframe.visible" width="800px" height="800px" append-to-body
-               :close-on-press-escape="false">
-      <iframe :src="iframe.url" width="100%" />
-    </el-dialog>
-
-    <!-- 展示形式:Form -->
-    <div ref="formRef" v-html="form.value" />
-
     <!-- 展示形式:BarCode 条形码 -->
     <el-dialog :title="barCode.title" :visible.sync="barCode.visible" width="500px" append-to-body
                :close-on-press-escape="false">
@@ -146,14 +137,6 @@ export default {
         title: '',
         visible: false,
       },
-      iframe: { // 展示形式:iframe
-        url: '',
-        title: '',
-        visible: false
-      },
-      form: { // 展示形式:form
-        html: '',
-      },
       barCode: { // 展示形式:条形码
         channelCode: '',
         value: '',
@@ -175,21 +158,24 @@ export default {
       // 1.1 未传递订单编号
       if (!this.id) {
         this.$message.error('未传递支付单号,无法查看对应的支付信息');
-        this.goBackToList();
+        this.goReturnUrl('cancel');
         return;
       }
       getOrder(this.id).then(response => {
         // 1.2 无法查询到支付信息
         if (!response.data) {
           this.$message.error('支付订单不存在,请检查!');
-          this.goBackToList();
+          this.goReturnUrl('cancel');
           return;
         }
-        // 1.3 订单已支付
-        // TODO 芋艿:已支付
-        if (response.data.status !== PayOrderStatusEnum.WAITING.status) {
-          this.$message.error('支付订单不处于待支付状态,请检查!');
-          this.goBackToList();
+        // 1.3 如果已支付、或者已关闭,则直接跳转
+        if (response.data.status === PayOrderStatusEnum.SUCCESS.status) {
+          this.$message.success('支付成功');
+          this.goReturnUrl('success');
+          return;
+        } else if (response.data.status === PayOrderStatusEnum.CLOSED.status) {
+          this.$message.error('无法支付,原因:订单已关闭');
+          this.goReturnUrl('close');
           return;
         }
 
@@ -218,15 +204,12 @@ export default {
       submitOrder({
         id: this.id,
         channelCode: channelCode,
+        returnUrl: location.href, // 支付成功后,支付渠道跳转回当前页;再由当前页,跳转回 {@link returnUrl} 对应的地址
         ...this.buildSubmitParam(channelCode)
       }).then(response => {
         const data = response.data
-        if (data.displayMode === PayDisplayModeEnum.IFRAME.mode) {
-          this.displayIFrame(channelCode, data)
-        } else if (data.displayMode === PayDisplayModeEnum.URL.mode) {
+        if (data.displayMode === PayDisplayModeEnum.URL.mode) {
           this.displayUrl(channelCode, data)
-        } else if (data.displayMode === PayDisplayModeEnum.FORM.mode) {
-          this.displayForm(channelCode, data)
         } else if (data.displayMode === PayDisplayModeEnum.QR_CODE.mode) {
           this.displayQrCode(channelCode, data)
         }
@@ -239,53 +222,7 @@ export default {
     },
     /** 构建提交支付的额外参数 */
     buildSubmitParam(channelCode) {
-      // ① 支付宝 PC 支付时,有多种展示形态
-      if (channelCode === PayChannelEnum.ALIPAY_PC.code) {
-        // 情况【前置模式】:将二维码前置到商户的订单确认页的模式。需要商户在自己的页面中以 iframe 方式请求支付宝页面。具体支持的枚举值有以下几种:
-        // 0:订单码-简约前置模式,对应 iframe 宽度不能小于 600px,高度不能小于 300px
-        // return {
-        //   "channelExtras": {
-        //     "qr_pay_mode": "0"
-        //   }
-        // }
-        // 1:订单码-前置模式,对应iframe 宽度不能小于 300px,高度不能小于 600px
-        // return {
-        //   "channelExtras": {
-        //     "qr_pay_mode": "1"
-        //   }
-        // }
-        // 3:订单码-迷你前置模式,对应 iframe 宽度不能小于 75px,高度不能小于 75px
-        // return {
-        //   "channelExtras": {
-        //     "qr_pay_mode": "3"
-        //   }
-        // }
-        // 4:订单码-可定义宽度的嵌入式二维码,商户可根据需要设定二维码的大小
-        // return {
-        //   "channelExtras": {
-        //     "qr_pay_mode": "4"
-        //   }
-        // }
-        // 情况【跳转模式】:跳转模式下,用户的扫码界面是由支付宝生成的,不在商户的域名下。支持传入的枚举值有
-        return {
-          "channelExtras": {
-            "qr_pay_mode": "2"
-          }
-        }
-        // 情况【表单模式】:直接提交当前页面到支付宝
-        // return {
-        //   displayMode: PayDisplayModeEnum.FORM.mode
-        // }
-      }
-
-      // ② 支付宝 Wap 支付时,引导手机扫码支付
-      if (channelCode === PayChannelEnum.ALIPAY_WAP.code) {
-        return {
-          displayMode: PayDisplayModeEnum.QR_CODE.mode
-        }
-      }
-
-      // ③ 支付宝 BarCode 支付时,需要传递 authCode 条形码
+      // ① 支付宝 BarCode 支付时,需要传递 authCode 条形码
       if (channelCode === PayChannelEnum.ALIPAY_BAR.code) {
         return {
           "channelExtras": {
@@ -295,37 +232,12 @@ export default {
       }
       return {}
     },
-    /** 提交支付后,IFrame 内置 URL 的展示形式 */
-    displayIFrame(channelCode, data) {
-      // TODO 芋艿:目前有点奇怪,支付宝总是会显示“支付环境存在风险”
-      this.iframe = {
-        title: '支付窗口',
-        url: data.displayContent,
-        visible: true
-      }
-      this.submitLoading = false
-    },
     /** 提交支付后,URL 的展示形式 */
     displayUrl(channelCode, data) {
-      // window.open(data.displayContent)window
+      // window.open(data.displayContent)
       location.href = data.displayContent
       this.submitLoading = false
     },
-    /** 提交支付后,Form 的展示形式 */
-    displayForm(channelCode, data) {
-      // 渲染支付页面
-      this.form = {
-        value: data.displayContent
-      }
-      // 防抖避免重复支付
-      this.$nextTick(() => {
-        // 提交支付表单
-        this.$refs.formRef.children[0].submit();
-        setTimeout(() => {
-          this.submitLoading = false
-        }, 1000);
-      });
-    },
     /** 提交支付后(支付宝扫码支付) */
     displayQrCode(channelCode, data) {
       let title = '请使用手机浏览器“扫一扫”';
@@ -354,13 +266,13 @@ export default {
           if (response.data.status === PayOrderStatusEnum.SUCCESS.status) {
             this.clearQueryInterval();
             this.$message.success('支付成功!');
-            this.goBackToList();
+            this.goReturnUrl();
           }
           // 已取消
           if (response.data.status === PayOrderStatusEnum.CLOSED.status) {
             this.clearQueryInterval();
             this.$message.error('支付已关闭!');
-            this.goBackToList();
+            this.goReturnUrl();
           }
         })
       }, 1000 * 2)
@@ -377,14 +289,34 @@ export default {
       clearInterval(this.interval)
       this.interval = undefined
     },
-    /** 回到列表 **/
-    goBackToList() {
-      this.$tab.closePage();
-      this.$router.go(-1);
-      // TODO 芋艿:需要优化;
-      // this.$router.push({
-      //   path: this.returnUrl
-      // });
+    /**
+     * 回到业务的 URL
+     *
+     * @param payResult 支付结果
+     *                  ① success:支付成功
+     *                  ② cancel:取消支付
+     *                  ③ close:支付已关闭
+     */
+    goReturnUrl(payResult) {
+      // 未配置的情况下,只能关闭
+      if (!this.returnUrl) {
+        this.$tab.closePage();
+        return
+      }
+
+      const url = this.returnUrl.indexOf('?') >= 0
+        ? this.returnUrl + '&payResult=' + payResult
+        : this.returnUrl + '?payResult=' + payResult
+      // 如果有配置,且是 http 开头,则浏览器跳转
+      if (this.returnUrl.indexOf('http') === 0) {
+        location.href = url;
+      } else {
+        this.$tab.closePage(() => {
+          this.$router.push({
+            path: url
+          });
+        });
+      }
     }
   }
 };