@cinerino/sdk 7.3.0-alpha.1 → 8.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/example/playground/public/lib/bundle.js +1 -1
- package/example/src/cloud/transaction/processPlaceOrderByCreditCard3DS.ts +461 -0
- package/example/src/transaction/processPlaceOrderByCreditCard3DS.ts +16 -14
- package/example/src/transaction/processPlaceOrderCOAEventByCreditCard.ts +11 -12
- package/example/src/transaction/processPlaceOrderCOAEventByMovieTicket.ts +2 -1
- package/lib/abstract/chevreTxn.d.ts +3 -3
- package/lib/abstract/cloud/txn/offer.d.ts +41 -0
- package/lib/abstract/cloud/txn/offer.js +137 -0
- package/lib/abstract/cloud/txn/transaction/placeOrder.d.ts +60 -0
- package/lib/abstract/cloud/txn/transaction/placeOrder.js +256 -0
- package/lib/abstract/cloud/txn/transaction/returnOrder.d.ts +21 -0
- package/lib/abstract/cloud/txn/transaction/returnOrder.js +155 -0
- package/lib/abstract/cloud/txn.d.ts +42 -0
- package/lib/abstract/cloud/txn.js +139 -0
- package/lib/abstract/index.d.ts +3 -1
- package/lib/abstract/index.js +24 -1
- package/lib/bundle.js +1064 -366
- package/lib/index.d.ts +2 -2
- package/lib/index.js +2 -1
- package/package.json +2 -2
|
@@ -3394,7 +3394,7 @@ var PayAssetTransactionService = /** @class */ (function (_super) {
|
|
|
3394
3394
|
return _super !== null && _super.apply(this, arguments) || this;
|
|
3395
3395
|
}
|
|
3396
3396
|
/**
|
|
3397
|
-
*
|
|
3397
|
+
* 決済カード認証
|
|
3398
3398
|
*/
|
|
3399
3399
|
PayAssetTransactionService.prototype.check = function (params) {
|
|
3400
3400
|
return __awaiter(this, void 0, void 0, function () {
|
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
// tslint:disable:no-console no-implicit-dependencies no-magic-numbers
|
|
2
|
+
import * as moment from 'moment';
|
|
3
|
+
import * as readline from 'readline';
|
|
4
|
+
import * as client from '../../../../lib/index';
|
|
5
|
+
import { auth } from '../../auth/clientCredentials';
|
|
6
|
+
|
|
7
|
+
const project = { id: String(process.env.PROJECT_ID) };
|
|
8
|
+
const profile = {
|
|
9
|
+
email: <string>process.env.TEST_PROFILE_EMAIL,
|
|
10
|
+
givenName: 'Taro',
|
|
11
|
+
familyName: 'SDK',
|
|
12
|
+
name: 'Taro ☆ SDK',
|
|
13
|
+
telephone: '+819012345678'
|
|
14
|
+
};
|
|
15
|
+
const paymentMethodType = 'CreditCard3DS';
|
|
16
|
+
const paymentServiceId = '664d98376fb87922bd6a4e52';
|
|
17
|
+
// 取引に使用するクレジットカード
|
|
18
|
+
const creditCard: client.factory.paymentMethod.paymentCard.creditCard.IUncheckedCardRaw = {
|
|
19
|
+
cardNo: '4100000000000100',
|
|
20
|
+
expire: '2812',
|
|
21
|
+
cardPass: '123',
|
|
22
|
+
holderName: 'AA AA'
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// tslint:disable-next-line:max-func-body-length
|
|
26
|
+
async function main() {
|
|
27
|
+
const eventService = new (await client.loadService()).Event({
|
|
28
|
+
endpoint: <string>process.env.API_ENDPOINT,
|
|
29
|
+
auth: await auth(),
|
|
30
|
+
project,
|
|
31
|
+
seller: { id: '' }
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const sellerService = new (await client.loadService()).Seller({
|
|
35
|
+
endpoint: <string>process.env.API_ENDPOINT,
|
|
36
|
+
auth: await auth(),
|
|
37
|
+
project
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const placeOrderService = await (await client.loadCloudTxn({
|
|
41
|
+
endpoint: <string>process.env.API_TXN_ENDPOINT,
|
|
42
|
+
auth: await auth()
|
|
43
|
+
})).createPlaceOrderInstance({
|
|
44
|
+
project,
|
|
45
|
+
seller: { id: '' }
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// 新しい決済サービス
|
|
49
|
+
const paymentService = await (await client.loadCloudPay({
|
|
50
|
+
endpoint: <string>process.env.API_PAY_ENDPOINT,
|
|
51
|
+
auth: await auth()
|
|
52
|
+
})).createPaymentInstance({
|
|
53
|
+
project,
|
|
54
|
+
seller: { id: '' }
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// 販売劇場検索
|
|
58
|
+
const searchSellersResult = await sellerService.search({ branchCode: { $eq: '001' } });
|
|
59
|
+
// tslint:disable-next-line:insecure-random
|
|
60
|
+
const seller = searchSellersResult.data[Math.floor(searchSellersResult.data.length * Math.random())];
|
|
61
|
+
if (seller === undefined) {
|
|
62
|
+
throw new Error('No seller');
|
|
63
|
+
}
|
|
64
|
+
console.log('ordering from seller...', (<client.factory.multilingualString>seller.name).ja);
|
|
65
|
+
|
|
66
|
+
// イベント検索
|
|
67
|
+
const searchScreeningEventsResult = await eventService.search<client.factory.eventType.ScreeningEvent>({
|
|
68
|
+
typeOf: client.factory.eventType.ScreeningEvent,
|
|
69
|
+
inSessionFrom: moment()
|
|
70
|
+
.toDate(),
|
|
71
|
+
inSessionThrough: moment()
|
|
72
|
+
.add(1, 'week')
|
|
73
|
+
.toDate()
|
|
74
|
+
});
|
|
75
|
+
console.log(searchScreeningEventsResult.data.length, 'events found');
|
|
76
|
+
|
|
77
|
+
const availableEvents = searchScreeningEventsResult.data;
|
|
78
|
+
if (availableEvents.length === 0) {
|
|
79
|
+
throw new Error('No available events');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
console.log('starting transaction...');
|
|
83
|
+
const transaction = await placeOrderService.start({
|
|
84
|
+
agent: {},
|
|
85
|
+
seller: { id: String(seller.id) },
|
|
86
|
+
object: {
|
|
87
|
+
// passport: { token: passportToken }
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
console.log('transaction started', transaction.id);
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
const numEvents = 1;
|
|
94
|
+
let amount = 0;
|
|
95
|
+
// tslint:disable-next-line:max-line-length
|
|
96
|
+
const authorizeSeatReservationResults: { price: number }[] = [];
|
|
97
|
+
|
|
98
|
+
// tslint:disable-next-line:no-increment-decrement
|
|
99
|
+
for (let i = 0; i < numEvents; i++) {
|
|
100
|
+
// イベント決定
|
|
101
|
+
// tslint:disable-next-line:insecure-random
|
|
102
|
+
const screeningEvent = availableEvents[Math.floor(availableEvents.length * Math.random())];
|
|
103
|
+
const authorizeSeatReservationResult = await authorizeSeatReservationByEvent({
|
|
104
|
+
event: screeningEvent,
|
|
105
|
+
transaction: transaction
|
|
106
|
+
});
|
|
107
|
+
amount += Number(authorizeSeatReservationResult.price);
|
|
108
|
+
authorizeSeatReservationResults.push(authorizeSeatReservationResult);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// 決済URL発行
|
|
112
|
+
const { paymentMethodId, paymentUrl } = await publishPaymentUrlAsyncForcibly({
|
|
113
|
+
object: {
|
|
114
|
+
amount,
|
|
115
|
+
paymentMethod: paymentMethodType,
|
|
116
|
+
method: '1',
|
|
117
|
+
creditCard: {
|
|
118
|
+
...creditCard,
|
|
119
|
+
retUrl: String(process.env.SECURE_TRAN_RET_URL) // callbackを指定すると3DSとして処理される
|
|
120
|
+
},
|
|
121
|
+
issuedThrough: { id: paymentServiceId }
|
|
122
|
+
},
|
|
123
|
+
purpose: { id: transaction.id, typeOf: client.factory.transactionType.PlaceOrder }
|
|
124
|
+
})({ paymentService });
|
|
125
|
+
console.log('paymentUrl published.', paymentMethodId, paymentUrl);
|
|
126
|
+
|
|
127
|
+
// wait callback...
|
|
128
|
+
await new Promise<void>((resolve, reject) => {
|
|
129
|
+
const rl = readline.createInterface({
|
|
130
|
+
input: process.stdin,
|
|
131
|
+
output: process.stdout
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
rl.question('callback received?:\n', async () => {
|
|
135
|
+
try {
|
|
136
|
+
console.log('authorizing credit card payment...');
|
|
137
|
+
const creditCardPaymentAuth = await authorizeCreditCardAsyncForcibly({
|
|
138
|
+
object: {
|
|
139
|
+
amount,
|
|
140
|
+
// amount: 1, // 間違えてみる
|
|
141
|
+
paymentMethod: paymentMethodType,
|
|
142
|
+
paymentMethodId, // URL発行時のpaymentMethodIdを指定
|
|
143
|
+
method: '1',
|
|
144
|
+
creditCard,
|
|
145
|
+
issuedThrough: { id: paymentServiceId }
|
|
146
|
+
},
|
|
147
|
+
purpose: { id: transaction.id, typeOf: client.factory.transactionType.PlaceOrder }
|
|
148
|
+
})({ paymentService });
|
|
149
|
+
console.log('credit card payment authorized', creditCardPaymentAuth.id);
|
|
150
|
+
|
|
151
|
+
// tslint:disable-next-line:no-magic-numbers
|
|
152
|
+
await wait(3000);
|
|
153
|
+
|
|
154
|
+
console.log('setting customer profile...');
|
|
155
|
+
await placeOrderService.setProfile({
|
|
156
|
+
id: transaction.id,
|
|
157
|
+
agent: profile
|
|
158
|
+
});
|
|
159
|
+
console.log('customer profile set');
|
|
160
|
+
|
|
161
|
+
await wait(3000);
|
|
162
|
+
|
|
163
|
+
// console.log('voiding credit card auth...');
|
|
164
|
+
// await paymentService.voidTransaction({
|
|
165
|
+
// id: creditCardPaymentAuth.id,
|
|
166
|
+
// object: { typeOf: client.factory.service.paymentService.PaymentServiceType.CreditCard },
|
|
167
|
+
// purpose: { id: transaction.id, typeOf: client.factory.transactionType.PlaceOrder }
|
|
168
|
+
// });
|
|
169
|
+
// console.log('credit card auth voided');
|
|
170
|
+
// await wait(3000);
|
|
171
|
+
// return;
|
|
172
|
+
|
|
173
|
+
console.log('confirming transaction...');
|
|
174
|
+
|
|
175
|
+
let confirmResult = await placeOrderService.confirmWithMiminalResponse({ id: transaction.id });
|
|
176
|
+
console.log('transaction confirmed', confirmResult);
|
|
177
|
+
|
|
178
|
+
// 何度確定をコールしても冪等
|
|
179
|
+
console.log('reconfirming transaction...');
|
|
180
|
+
confirmResult = await placeOrderService.confirmWithMiminalResponse({ id: transaction.id });
|
|
181
|
+
console.log('transaction reconfirmed', confirmResult);
|
|
182
|
+
resolve();
|
|
183
|
+
} catch (error) {
|
|
184
|
+
reject(error);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
} catch (error) {
|
|
189
|
+
console.error(error);
|
|
190
|
+
|
|
191
|
+
await wait(3000);
|
|
192
|
+
|
|
193
|
+
console.log('canceling transaction...');
|
|
194
|
+
await placeOrderService.cancel({ id: transaction.id });
|
|
195
|
+
console.log('transaction canceled.');
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
type IAuthorizeReservationAction = Pick<
|
|
200
|
+
client.factory.action.authorize.offer.eventService.IAction<client.factory.service.webAPI.Identifier.Chevre>,
|
|
201
|
+
'id'
|
|
202
|
+
> & {
|
|
203
|
+
result?: {
|
|
204
|
+
price?: number;
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
// tslint:disable-next-line:max-func-body-length
|
|
209
|
+
async function authorizeSeatReservationByEvent(params: {
|
|
210
|
+
event: client.factory.event.screeningEvent.IEvent;
|
|
211
|
+
transaction: Pick<client.factory.transaction.placeOrder.ITransaction, 'id'>;
|
|
212
|
+
}): Promise<{
|
|
213
|
+
price: number;
|
|
214
|
+
}> {
|
|
215
|
+
const eventService = new (await client.loadService()).Event({
|
|
216
|
+
endpoint: <string>process.env.API_ENDPOINT,
|
|
217
|
+
auth: await auth(),
|
|
218
|
+
project,
|
|
219
|
+
seller: { id: '' }
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
const offerService = new (await client.loadService()).Offer({
|
|
223
|
+
endpoint: <string>process.env.API_ENDPOINT,
|
|
224
|
+
auth: await auth(),
|
|
225
|
+
project,
|
|
226
|
+
seller: { id: '' }
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
const screeningEvent = params.event;
|
|
230
|
+
const transaction = params.transaction;
|
|
231
|
+
|
|
232
|
+
// 券種検索
|
|
233
|
+
let ticketOffers = await eventService.searchTicketOffers({
|
|
234
|
+
event: { id: screeningEvent.id }
|
|
235
|
+
});
|
|
236
|
+
console.log('チケットオファーは以下の通りです');
|
|
237
|
+
console.log(ticketOffers.map((o) => {
|
|
238
|
+
const unitPriceSpecification = o.priceSpecification.priceComponent
|
|
239
|
+
.filter((s) => s.typeOf === client.factory.priceSpecificationType.UnitPriceSpecification)
|
|
240
|
+
.map((s) => `単価:${s.price}/${(<client.factory.priceSpecification.IPriceSpecification<client.factory.priceSpecificationType.UnitPriceSpecification>>s).referenceQuantity.value}`)
|
|
241
|
+
.join(' ');
|
|
242
|
+
const categoryCodeCharge = o.priceSpecification.priceComponent
|
|
243
|
+
.filter((s) => s.typeOf === client.factory.priceSpecificationType.CategoryCodeChargeSpecification)
|
|
244
|
+
.map((s) => `+${(<client.factory.priceSpecification.IPriceSpecification<client.factory.priceSpecificationType.CategoryCodeChargeSpecification>>s).appliesToCategoryCode[0].codeValue}チャージ:${s.price} ${s.priceCurrency}`)
|
|
245
|
+
.join(' ');
|
|
246
|
+
|
|
247
|
+
return `${o.id} ${(<client.factory.multilingualString>o.name).ja} ${unitPriceSpecification} ${o.priceCurrency} ${categoryCodeCharge}`;
|
|
248
|
+
})
|
|
249
|
+
.join('\n'));
|
|
250
|
+
|
|
251
|
+
// 空席検索
|
|
252
|
+
const searchSeatOffersResult = await eventService.searchSeats({ event: { id: screeningEvent.id } });
|
|
253
|
+
const seatOffers = searchSeatOffersResult.data;
|
|
254
|
+
// console.log(seatOffers.length, 'seatOffers found');
|
|
255
|
+
// const seatOffers = offers[0].containsPlace;
|
|
256
|
+
console.log(seatOffers.length, 'seatOffers found');
|
|
257
|
+
const availableSeatOffers
|
|
258
|
+
= seatOffers.filter((o) => o.offers?.shift()?.availability === client.factory.itemAvailability.InStock);
|
|
259
|
+
console.log(availableSeatOffers.length, 'availableSeatOffers found');
|
|
260
|
+
if (availableSeatOffers.length <= 0) {
|
|
261
|
+
throw new Error('No available seats');
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// ムビチケ以外のメンバーシップオファーを選択
|
|
265
|
+
ticketOffers = ticketOffers
|
|
266
|
+
.filter((offer) => {
|
|
267
|
+
const movieTicketTypeChargeSpecification = offer.priceSpecification.priceComponent.find(
|
|
268
|
+
(component) => component.typeOf === client.factory.priceSpecificationType.MovieTicketTypeChargeSpecification
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
return movieTicketTypeChargeSpecification === undefined;
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
const selectedTicketOffer = ticketOffers.shift();
|
|
275
|
+
if (selectedTicketOffer === undefined) {
|
|
276
|
+
throw new Error('selectedTicketOffer undefined');
|
|
277
|
+
}
|
|
278
|
+
console.log('ticket offer selected', selectedTicketOffer.id, selectedTicketOffer.identifier, selectedTicketOffer.name.ja);
|
|
279
|
+
|
|
280
|
+
// 座席をランダムに選択
|
|
281
|
+
const selectedScreeningRoomSection = String(availableSeatOffers[0].containedInPlace?.branchCode);
|
|
282
|
+
console.log('screening room section selected', selectedScreeningRoomSection);
|
|
283
|
+
console.log(selectedScreeningRoomSection);
|
|
284
|
+
const selectedSeatOffers = availableSeatOffers.slice(0, 1);
|
|
285
|
+
console.log(selectedSeatOffers.length, 'seats selected');
|
|
286
|
+
|
|
287
|
+
await wait(3000);
|
|
288
|
+
console.log('authorizing seat reservation...');
|
|
289
|
+
const seatReservationAuth = <IAuthorizeReservationAction>await offerService.authorizeEventService({
|
|
290
|
+
object: {
|
|
291
|
+
reservationFor: {
|
|
292
|
+
id: screeningEvent.id
|
|
293
|
+
},
|
|
294
|
+
acceptedOffer: selectedSeatOffers.map((o) => {
|
|
295
|
+
return {
|
|
296
|
+
typeOf: selectedTicketOffer.typeOf,
|
|
297
|
+
id: String(selectedTicketOffer.id),
|
|
298
|
+
itemOffered: {
|
|
299
|
+
serviceOutput: {
|
|
300
|
+
typeOf: client.factory.reservationType.EventReservation,
|
|
301
|
+
reservedTicket: {
|
|
302
|
+
typeOf: 'Ticket',
|
|
303
|
+
ticketedSeat: {
|
|
304
|
+
typeOf: client.factory.placeType.Seat,
|
|
305
|
+
seatNumber: o.branchCode,
|
|
306
|
+
seatSection: selectedScreeningRoomSection,
|
|
307
|
+
seatRow: ''
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
additionalProperty: [{ name: 'sampleName', value: 'sampleValue' }]
|
|
313
|
+
};
|
|
314
|
+
})
|
|
315
|
+
},
|
|
316
|
+
purpose: { id: transaction.id, typeOf: client.factory.transactionType.PlaceOrder }
|
|
317
|
+
});
|
|
318
|
+
console.log('seat reservation authorized', seatReservationAuth.id);
|
|
319
|
+
|
|
320
|
+
const price = seatReservationAuth.result?.price;
|
|
321
|
+
// 金額計算
|
|
322
|
+
if (typeof price !== 'number') {
|
|
323
|
+
throw new Error('result.price undefined');
|
|
324
|
+
}
|
|
325
|
+
console.log('price:', price);
|
|
326
|
+
|
|
327
|
+
return { price };
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
async function wait(waitInMilliseconds: number) {
|
|
331
|
+
return new Promise((resolve) => setTimeout(resolve, waitInMilliseconds));
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
const USE_FORCE_AUTHORIZE_PAYMENT_ASYNC_GIVE_UP_SECONDS = 10;
|
|
335
|
+
const USE_FORCE_AUTHORIZE_PAYMENT_ASYNC_CHECK_INTERVAL_MS = 1000;
|
|
336
|
+
function publishPaymentUrlAsyncForcibly(params: {
|
|
337
|
+
object: Pick<client.factory.action.authorize.paymentMethod.any.IObjectWithoutDetail, 'amount' | 'creditCard' | 'issuedThrough' | 'paymentMethod' | 'method'>;
|
|
338
|
+
purpose: {
|
|
339
|
+
typeOf: client.factory.transactionType.PlaceOrder;
|
|
340
|
+
id: string;
|
|
341
|
+
};
|
|
342
|
+
}) {
|
|
343
|
+
return async (repos: {
|
|
344
|
+
paymentService: client.cloudPay.service.Payment;
|
|
345
|
+
}): Promise<client.factory.action.accept.pay.IResult> => {
|
|
346
|
+
const acceptTask = await repos.paymentService.publishCreditCardPaymentUrlAsync(params);
|
|
347
|
+
const giveUpPayment = moment()
|
|
348
|
+
.add(USE_FORCE_AUTHORIZE_PAYMENT_ASYNC_GIVE_UP_SECONDS, 'seconds');
|
|
349
|
+
let result: client.factory.action.accept.pay.IResult | undefined;
|
|
350
|
+
let error: { name?: string; message?: string } | undefined;
|
|
351
|
+
|
|
352
|
+
// n秒おきに状態確認
|
|
353
|
+
while (result === undefined && error === undefined) {
|
|
354
|
+
await wait(USE_FORCE_AUTHORIZE_PAYMENT_ASYNC_CHECK_INTERVAL_MS); // n秒待機
|
|
355
|
+
|
|
356
|
+
// タスク作成から一定時間経過すればあきらめる
|
|
357
|
+
if (moment()
|
|
358
|
+
.isAfter(giveUpPayment)) {
|
|
359
|
+
error = new client.factory.errors.GatewayTimeout('action given up');
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const acceptAction = await repos.paymentService.findAcceptPayAction({
|
|
364
|
+
sameAs: { id: acceptTask.id },
|
|
365
|
+
purpose: params.purpose
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
// CompletedActionStatusであればタスク完了とみなす
|
|
369
|
+
if (acceptAction.actionStatus === client.factory.actionStatusType.CompletedActionStatus
|
|
370
|
+
&& acceptAction.result !== undefined) {
|
|
371
|
+
result = acceptAction.result;
|
|
372
|
+
break;
|
|
373
|
+
} else {
|
|
374
|
+
// 待機続行
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// エラーが存在すれば、これ以上待機する価値はなし
|
|
378
|
+
if (acceptAction.error !== undefined) {
|
|
379
|
+
error = acceptAction.error;
|
|
380
|
+
break;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if (typeof result?.paymentMethodId === 'string') {
|
|
385
|
+
return result;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
throw error;
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function authorizeCreditCardAsyncForcibly(params: {
|
|
393
|
+
object: Pick<
|
|
394
|
+
client.factory.action.authorize.paymentMethod.any.IObjectWithoutDetail,
|
|
395
|
+
'amount' | 'issuedThrough' | 'paymentMethod' | 'creditCard' | 'method' | 'paymentMethodId' | 'name' | 'additionalProperty'
|
|
396
|
+
>;
|
|
397
|
+
purpose: {
|
|
398
|
+
typeOf: client.factory.transactionType.PlaceOrder;
|
|
399
|
+
id: string;
|
|
400
|
+
};
|
|
401
|
+
}) {
|
|
402
|
+
return async (repos: {
|
|
403
|
+
paymentService: client.cloudPay.service.Payment;
|
|
404
|
+
}): Promise<{ id: string }> => {
|
|
405
|
+
// 決済承認タスク作成
|
|
406
|
+
const authorizeTask = await repos.paymentService.authorizeCreditCardAsync(params);
|
|
407
|
+
const giveUpPayment = moment()
|
|
408
|
+
.add(USE_FORCE_AUTHORIZE_PAYMENT_ASYNC_GIVE_UP_SECONDS, 'seconds');
|
|
409
|
+
let result: { id: string } | undefined;
|
|
410
|
+
let error: { name?: string; message?: string } | undefined;
|
|
411
|
+
|
|
412
|
+
// n秒おきに状態確認
|
|
413
|
+
while (result === undefined && error === undefined) {
|
|
414
|
+
await wait(USE_FORCE_AUTHORIZE_PAYMENT_ASYNC_CHECK_INTERVAL_MS); // n秒待機
|
|
415
|
+
|
|
416
|
+
// タスク作成から一定時間経過すればあきらめる
|
|
417
|
+
if (moment()
|
|
418
|
+
.isAfter(giveUpPayment)) {
|
|
419
|
+
error = new client.factory.errors.GatewayTimeout('action given up');
|
|
420
|
+
break;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
const authorizeAction = await repos.paymentService.findAuthorizeAction({
|
|
424
|
+
sameAs: { id: authorizeTask.id },
|
|
425
|
+
object: {
|
|
426
|
+
typeOf: client.factory.service.paymentService.PaymentServiceType.CreditCard
|
|
427
|
+
},
|
|
428
|
+
purpose: params.purpose
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
// アクションIDが存在し、CompletedActionStatusであればタスク完了とみなす
|
|
432
|
+
if (typeof authorizeAction.id === 'string') {
|
|
433
|
+
if (authorizeAction.actionStatus === client.factory.actionStatusType.CompletedActionStatus) {
|
|
434
|
+
// ステータス完了であれば決済承認アクションIDを保管
|
|
435
|
+
result = { id: authorizeAction.id };
|
|
436
|
+
break;
|
|
437
|
+
} else {
|
|
438
|
+
// 待機続行
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// エラーが存在すれば、これ以上待機する価値はなし
|
|
443
|
+
if (authorizeAction.error !== undefined) {
|
|
444
|
+
error = authorizeAction.error;
|
|
445
|
+
break;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
if (typeof result?.id === 'string') {
|
|
450
|
+
return result;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
throw error;
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
main()
|
|
458
|
+
.then(() => {
|
|
459
|
+
console.log('success!');
|
|
460
|
+
})
|
|
461
|
+
.catch(console.error);
|
|
@@ -88,19 +88,7 @@ async function main() {
|
|
|
88
88
|
});
|
|
89
89
|
console.log('transaction started', transaction.id);
|
|
90
90
|
|
|
91
|
-
// 購入者情報入力時間
|
|
92
|
-
// tslint:disable-next-line:no-magic-numbers
|
|
93
|
-
await wait(3000);
|
|
94
|
-
|
|
95
|
-
console.log('setting customer profile...');
|
|
96
|
-
await placeOrderService.setProfile({
|
|
97
|
-
id: transaction.id,
|
|
98
|
-
agent: profile
|
|
99
|
-
});
|
|
100
|
-
console.log('customer profile set');
|
|
101
|
-
|
|
102
91
|
try {
|
|
103
|
-
|
|
104
92
|
const numEvents = 1;
|
|
105
93
|
let amount = 0;
|
|
106
94
|
// tslint:disable-next-line:max-line-length
|
|
@@ -159,6 +147,16 @@ async function main() {
|
|
|
159
147
|
})({ paymentService });
|
|
160
148
|
console.log('credit card payment authorized', creditCardPaymentAuth.id);
|
|
161
149
|
|
|
150
|
+
// tslint:disable-next-line:no-magic-numbers
|
|
151
|
+
await wait(3000);
|
|
152
|
+
|
|
153
|
+
console.log('setting customer profile...');
|
|
154
|
+
await placeOrderService.setProfile({
|
|
155
|
+
id: transaction.id,
|
|
156
|
+
agent: profile
|
|
157
|
+
});
|
|
158
|
+
console.log('customer profile set');
|
|
159
|
+
|
|
162
160
|
await wait(3000);
|
|
163
161
|
|
|
164
162
|
// console.log('voiding credit card auth...');
|
|
@@ -173,9 +171,13 @@ async function main() {
|
|
|
173
171
|
|
|
174
172
|
console.log('confirming transaction...');
|
|
175
173
|
|
|
176
|
-
|
|
177
|
-
console.log('transaction confirmed', confirmResult
|
|
174
|
+
let confirmResult = await placeOrderService.confirmWithMiminalResponse({ id: transaction.id });
|
|
175
|
+
console.log('transaction confirmed', confirmResult);
|
|
178
176
|
|
|
177
|
+
// 何度確定をコールしても冪等
|
|
178
|
+
console.log('reconfirming transaction...');
|
|
179
|
+
confirmResult = await placeOrderService.confirmWithMiminalResponse({ id: transaction.id });
|
|
180
|
+
console.log('transaction reconfirmed', confirmResult);
|
|
179
181
|
resolve();
|
|
180
182
|
} catch (error) {
|
|
181
183
|
reject(error);
|
|
@@ -95,17 +95,6 @@ async function main() {
|
|
|
95
95
|
});
|
|
96
96
|
console.log('transaction started', transaction.id);
|
|
97
97
|
|
|
98
|
-
// 購入者情報入力時間
|
|
99
|
-
// tslint:disable-next-line:no-magic-numbers
|
|
100
|
-
await wait(3000);
|
|
101
|
-
|
|
102
|
-
console.log('setting customer profile...');
|
|
103
|
-
await placeOrderService.setProfile({
|
|
104
|
-
id: transaction.id,
|
|
105
|
-
agent: profile
|
|
106
|
-
});
|
|
107
|
-
console.log('customer profile set');
|
|
108
|
-
|
|
109
98
|
try {
|
|
110
99
|
|
|
111
100
|
let amount = 0;
|
|
@@ -166,6 +155,16 @@ async function main() {
|
|
|
166
155
|
// tslint:disable-next-line:no-magic-numbers
|
|
167
156
|
await wait(3000);
|
|
168
157
|
|
|
158
|
+
console.log('setting customer profile...');
|
|
159
|
+
await placeOrderService.setProfile({
|
|
160
|
+
id: transaction.id,
|
|
161
|
+
agent: profile
|
|
162
|
+
});
|
|
163
|
+
console.log('customer profile set');
|
|
164
|
+
|
|
165
|
+
// tslint:disable-next-line:no-magic-numbers
|
|
166
|
+
await wait(3000);
|
|
167
|
+
|
|
169
168
|
// 取引を中止する場合はコチラ↓
|
|
170
169
|
// console.log('取引を中止します...');
|
|
171
170
|
// await placeOrderService.cancel({ transactionId: transaction.id });
|
|
@@ -233,7 +232,7 @@ async function authorizeSeatReservationByEvent(params: {
|
|
|
233
232
|
object: {
|
|
234
233
|
event: {
|
|
235
234
|
id: params.event.id
|
|
236
|
-
// id: '
|
|
235
|
+
// id: '120162210202406211200920'
|
|
237
236
|
},
|
|
238
237
|
acceptedOffer: [
|
|
239
238
|
{
|
|
@@ -45,8 +45,8 @@ export declare namespace service {
|
|
|
45
45
|
export declare class ChevreTxn {
|
|
46
46
|
options: Pick<IOptions, 'auth' | 'endpoint'>;
|
|
47
47
|
constructor(options: Pick<IOptions, 'auth' | 'endpoint'>);
|
|
48
|
-
createOfferInstance(params: Pick<IOptions, 'project'> & Pick<IAdditionalOptions, 'seller'>): Promise<OfferService>;
|
|
48
|
+
createOfferInstance(params: Pick<IOptions, 'project' | 'retryableStatusCodes'> & Pick<IAdditionalOptions, 'seller'>): Promise<OfferService>;
|
|
49
49
|
createMoneyTransferTransactionInstance(params: Pick<IOptions, 'project'> & Pick<IAdditionalOptions, 'seller'>): Promise<MoneyTransferTransactionService>;
|
|
50
|
-
createPlaceOrderTransactionInstance(params: Pick<IOptions, 'project'> & Pick<IAdditionalOptions, 'seller'>): Promise<PlaceOrderTransactionService>;
|
|
51
|
-
createReturnOrderTransactionInstance(params: Pick<IOptions, 'project'> & Pick<IAdditionalOptions, 'seller'>): Promise<ReturnOrderTransactionService>;
|
|
50
|
+
createPlaceOrderTransactionInstance(params: Pick<IOptions, 'project' | 'retryableStatusCodes'> & Pick<IAdditionalOptions, 'seller'>): Promise<PlaceOrderTransactionService>;
|
|
51
|
+
createReturnOrderTransactionInstance(params: Pick<IOptions, 'project' | 'retryableStatusCodes'> & Pick<IAdditionalOptions, 'seller'>): Promise<ReturnOrderTransactionService>;
|
|
52
52
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { IAuthorizeEventServiceResult, IMinimalAuthorizeEventServiceResult } from '../../chevreTxn/transaction/placeOrder/factory';
|
|
2
|
+
import * as factory from '../../factory';
|
|
3
|
+
import { IAdditionalOptions, IOptions, Service } from '../../service';
|
|
4
|
+
/**
|
|
5
|
+
* オファーサービス
|
|
6
|
+
*/
|
|
7
|
+
export declare class OfferService extends Service {
|
|
8
|
+
constructor(options: Pick<IOptions, 'auth' | 'endpoint' | 'transporter' | 'project' | 'defaultPath' | 'retryableStatusCodes'> & IAdditionalOptions);
|
|
9
|
+
/**
|
|
10
|
+
* 興行オファー承認
|
|
11
|
+
*/
|
|
12
|
+
authorizeEventService(params: {
|
|
13
|
+
object: factory.action.authorize.offer.eventService.IObjectWithoutDetail<factory.service.webAPI.Identifier.Chevre>;
|
|
14
|
+
purpose: factory.action.authorize.offer.eventService.IPurpose;
|
|
15
|
+
}, options?: {
|
|
16
|
+
/**
|
|
17
|
+
* レスポンスを最小化する
|
|
18
|
+
* Promise<IMinimalAuthorizeEventServiceResult>が返ります
|
|
19
|
+
*/
|
|
20
|
+
expectsMinimalResponse?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* オファー未指定(座席をホールドするのみ)
|
|
23
|
+
*/
|
|
24
|
+
noOfferSpecified?: boolean;
|
|
25
|
+
}): Promise<IAuthorizeEventServiceResult | IMinimalAuthorizeEventServiceResult>;
|
|
26
|
+
/**
|
|
27
|
+
* 興行オファー承認取消
|
|
28
|
+
*/
|
|
29
|
+
voidAuthorization(params: {
|
|
30
|
+
/**
|
|
31
|
+
* アクションID
|
|
32
|
+
*/
|
|
33
|
+
id: string;
|
|
34
|
+
object: {
|
|
35
|
+
itemOffered: {
|
|
36
|
+
typeOf: factory.product.ProductType.EventService;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
purpose: factory.action.authorize.offer.eventService.IPurpose;
|
|
40
|
+
}): Promise<void>;
|
|
41
|
+
}
|