test-payment-methods.ts 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. import { Payment, PaymentMethodHandler, TransactionalConnection } from '@vendure/core';
  2. import { vi } from 'vitest';
  3. import { LanguageCode } from '../graphql/generated-e2e-admin-types';
  4. export const testSuccessfulPaymentMethod = new PaymentMethodHandler({
  5. code: 'test-payment-method',
  6. description: [{ languageCode: LanguageCode.en, value: 'Test Payment Method' }],
  7. args: {},
  8. createPayment: (ctx, order, amount, args, metadata) => {
  9. return {
  10. amount,
  11. state: 'Settled',
  12. transactionId: '12345',
  13. metadata: { public: metadata },
  14. };
  15. },
  16. settlePayment: () => ({
  17. success: true,
  18. }),
  19. });
  20. export const onTransitionSpy = vi.fn();
  21. export const onCancelPaymentSpy = vi.fn();
  22. /**
  23. * A two-stage (authorize, capture) payment method, with no createRefund method.
  24. */
  25. export const twoStagePaymentMethod = new PaymentMethodHandler({
  26. code: 'authorize-only-payment-method',
  27. description: [{ languageCode: LanguageCode.en, value: 'Test Payment Method' }],
  28. args: {},
  29. createPayment: (ctx, order, amount, args, metadata) => {
  30. return {
  31. amount,
  32. state: 'Authorized',
  33. transactionId: '12345-' + order.code,
  34. metadata: { public: metadata },
  35. };
  36. },
  37. settlePayment: () => {
  38. return {
  39. success: true,
  40. metadata: {
  41. moreData: 42,
  42. },
  43. };
  44. },
  45. cancelPayment: (...args) => {
  46. onCancelPaymentSpy(...args);
  47. return {
  48. success: true,
  49. metadata: {
  50. cancellationCode: '12345',
  51. },
  52. };
  53. },
  54. onStateTransitionStart: (fromState, toState, data) => {
  55. onTransitionSpy(fromState, toState, data);
  56. },
  57. });
  58. /**
  59. * A method that can be used to pay for only part of the order (allowing us to test multiple payments
  60. * per order).
  61. */
  62. export const partialPaymentMethod = new PaymentMethodHandler({
  63. code: 'partial-payment-method',
  64. description: [{ languageCode: LanguageCode.en, value: 'Partial Payment Method' }],
  65. args: {},
  66. createPayment: (ctx, order, amount, args, metadata) => {
  67. return {
  68. amount: metadata.amount,
  69. state: metadata.authorizeOnly ? 'Authorized' : 'Settled',
  70. transactionId: '12345',
  71. metadata: { public: metadata },
  72. };
  73. },
  74. settlePayment: () => {
  75. return {
  76. success: true,
  77. };
  78. },
  79. });
  80. /**
  81. * A payment method which includes a createRefund method.
  82. */
  83. export const singleStageRefundablePaymentMethod = new PaymentMethodHandler({
  84. code: 'single-stage-refundable-payment-method',
  85. description: [{ languageCode: LanguageCode.en, value: 'Test Payment Method' }],
  86. args: {},
  87. createPayment: (ctx, order, amount, args, metadata) => {
  88. return {
  89. amount,
  90. state: 'Settled',
  91. transactionId: '12345',
  92. metadata,
  93. };
  94. },
  95. settlePayment: () => {
  96. return { success: true };
  97. },
  98. createRefund: (ctx, input, amount, order, payment, args) => {
  99. return {
  100. state: 'Settled',
  101. transactionId: 'abc123',
  102. metadata: { amount },
  103. };
  104. },
  105. });
  106. let connection: TransactionalConnection;
  107. /**
  108. * A payment method where a Refund attempt will fail the first time
  109. */
  110. export const singleStageRefundFailingPaymentMethod = new PaymentMethodHandler({
  111. code: 'single-stage-refund-failing-payment-method',
  112. description: [{ languageCode: LanguageCode.en, value: 'Test Payment Method' }],
  113. args: {},
  114. init: injector => {
  115. connection = injector.get(TransactionalConnection);
  116. },
  117. createPayment: (ctx, order, amount, args, metadata) => {
  118. return {
  119. amount,
  120. state: 'Settled',
  121. transactionId: '12345',
  122. metadata,
  123. };
  124. },
  125. settlePayment: () => {
  126. return { success: true };
  127. },
  128. createRefund: async (ctx, input, amount, order, payment, args) => {
  129. const paymentWithRefunds = await connection
  130. .getRepository(ctx, Payment)
  131. .findOne({ where: { id: payment.id }, relations: ['refunds'] });
  132. const isFirstRefundAttempt = paymentWithRefunds?.refunds.length === 0;
  133. const metadata = isFirstRefundAttempt ? { errorMessage: 'Service temporarily unavailable' } : {};
  134. return {
  135. state: isFirstRefundAttempt ? 'Failed' : 'Settled',
  136. metadata,
  137. };
  138. },
  139. });
  140. /**
  141. * A payment method where calling `settlePayment` always fails.
  142. */
  143. export const failsToSettlePaymentMethod = new PaymentMethodHandler({
  144. code: 'fails-to-settle-payment-method',
  145. description: [{ languageCode: LanguageCode.en, value: 'Test Payment Method' }],
  146. args: {},
  147. createPayment: (ctx, order, amount, args, metadata) => {
  148. return {
  149. amount,
  150. state: 'Authorized',
  151. transactionId: '12345-' + order.code,
  152. metadata: {
  153. privateCreatePaymentData: 'secret',
  154. public: {
  155. publicCreatePaymentData: 'public',
  156. },
  157. },
  158. };
  159. },
  160. settlePayment: () => {
  161. return {
  162. success: false,
  163. state: 'Cancelled',
  164. errorMessage: 'Something went horribly wrong',
  165. metadata: {
  166. privateSettlePaymentData: 'secret',
  167. public: {
  168. publicSettlePaymentData: 'public',
  169. },
  170. },
  171. };
  172. },
  173. });
  174. /**
  175. * A payment method where calling `settlePayment` always fails.
  176. */
  177. export const failsToCancelPaymentMethod = new PaymentMethodHandler({
  178. code: 'fails-to-cancel-payment-method',
  179. description: [{ languageCode: LanguageCode.en, value: 'Test Payment Method' }],
  180. args: {},
  181. createPayment: (ctx, order, amount, args, metadata) => {
  182. return {
  183. amount,
  184. state: 'Authorized',
  185. transactionId: '12345-' + order.code,
  186. };
  187. },
  188. settlePayment: () => {
  189. return {
  190. success: true,
  191. };
  192. },
  193. cancelPayment: (ctx, order, payment) => {
  194. return {
  195. success: false,
  196. errorMessage: 'something went horribly wrong',
  197. state: payment.state !== 'Cancelled' ? payment.state : undefined,
  198. metadata: {
  199. cancellationData: 'foo',
  200. },
  201. };
  202. },
  203. });
  204. export const testFailingPaymentMethod = new PaymentMethodHandler({
  205. code: 'test-failing-payment-method',
  206. description: [{ languageCode: LanguageCode.en, value: 'Test Failing Payment Method' }],
  207. args: {},
  208. createPayment: (ctx, order, amount, args, metadata) => {
  209. return {
  210. amount,
  211. state: 'Declined',
  212. errorMessage: 'Insufficient funds',
  213. metadata: { public: metadata },
  214. };
  215. },
  216. settlePayment: () => ({
  217. success: true,
  218. }),
  219. });
  220. export const testErrorPaymentMethod = new PaymentMethodHandler({
  221. code: 'test-error-payment-method',
  222. description: [{ languageCode: LanguageCode.en, value: 'Test Error Payment Method' }],
  223. args: {},
  224. createPayment: (ctx, order, amount, args, metadata) => {
  225. return {
  226. amount,
  227. state: 'Error',
  228. errorMessage: 'Something went horribly wrong',
  229. metadata,
  230. };
  231. },
  232. settlePayment: () => ({
  233. success: true,
  234. }),
  235. });